Compilar un Kernel en Debian, Ubuntu y derivados

Manual para compilar un kernel, aplicar parches y compilar módulos para Debian, ubuntu y derivados Alejandro Garrido Mota <garridomota@gmail.com>

Conceptos básicos

Si posees conocimientos de GNU/Linux y sistemas operativos puedes aventurarte a la próxima sección; en la presente discutiremos conceptos básicos.

Cuando hablamos de "Linux" es frecuente referirnos al sistema operativo y sus aplicaciones y no al núcleo del sistema. La realidad es que Linux es solamente el núcleo del sistema (también denominado kernel): componente de gran envergadura que hace operar nuestra computadora. Entre las funciones más importantes del kernel:

  • Administración de la memoria del computador.
  • Establecimiento de la comunicación entre aplicaciones y dispositivos de hardware.
  • Administración de procesos (o tareas).

Aunque no son las únicas, si son las de más relevancia. Vale recalcar que el núcleo Linux se caracteriza por ser muy volátil y tener céleres desarrolladores al momento de corregir un problema o agregar una nueva característica al núcleo; recibiendo así gran cantidad de actualizaciones en poco tiempo. Dichas actualizaciones comúnmente contienen nuevos módulos, mejoras de seguridad, administración de recursos y muchas otras características. ¿Cómo averiguar que innovaciones incorpora determinado núcleo? Observando un archivo incorporado en el mismo llamado ChangLog. Asimismo es factible descargar y observar el archivo de texto plano Changelog desde la página oficial del proyecto. Muchas veces surgen dudas acerca de la necesidad de compilar el kernel cuando liberan una nueva versión: no debemos dudar, solamente se compila una nueva versión de kernel cuando tenemos dispositivos de hardware muy recientes y nos vemos forzados a migrar hacia una versión que incluya módulos para el soporte de este. Otra razón se basa en que poseemos una versión muy antigua y optamos por actualizarlo para tener mejoras en la administración de memoria, procesos, recursos, etc. Actualmente ocurre esto con la rama 2.4 y 2.6 del kernel Linux; algunos servidores poseen la 2.4 y compilan la versión de la rama (2.6.X) con el objetivo de mejorar la administración de recursos, ya que esta última es más eficaz.

El kernel NO se actualiza, si deseas una nueva versión debes descargarla de la página oficial del proyecto y compilarla. También puedes buscar un paquete (por ejemplo en los repositorios de Debian) con una versión ya compilada para tu arquitectura de hardware; evitando la tarea de compilar y desaprovechando la optimización del sistema.

¿Porqué compilar un kernel a la manera Debian?

Dejar de compilar un kernel por la vertiente clásica para hacerlo a la manera Debian (debian way) proporciona muchas ventajas: motivo a que se empaqueta se crea un paquete con extensión .deb. Cualquier buen administrador de sistemas sabe las principales ventajas de que se genere un paquete, entre las principales:

  • Cuando tengamos que eliminar el kernel (quizás porque ya hayamos compilado una nueva versión, por ejemplo), lo único que debemos hacer es utilizar la herramienta dpkg de la siguiente manera: dpkg -r TU_KERNEL. Donde TU_KERNEL es el nombre que le diste al paquete (ya más adelante detallaremos esto). Para eliminar el kernel también puedes utilizar herramientas como apt-get, aptitude, o mejor aún Synaptic para los usuarios novel que están comenzando con Linux.
  • Tener un paquete con nuestro kernel facilita guardarlo en un Pendrive, CD, DVD, o mejor aún: si tenemos un servidor web es factible distribuirlo. El principal objetivo de esto es tener la posibilidad de instalar ese mismo kernel en varias máquinas. Debian está implementando esta característica desde hace mucho años, ofrece kernel's pre-compilados para tu computador en sus repositorios de paquetes, de manera que si eres un usuario final, te da pereza compilar el kernel o no estés en la necesidad de hacerlo tengas la posibilidad de elegir el paquete (kernel) entre la gran variedad que hay e instalarlo con algún gestor de paquetes como aptitude, apt, dpkg.

Ejemplo práctico

Imagina que en tu trabajo gestionas información de gran envergadura y no deseas que los usuarios puedan hacer uso de pendrives ni dispositivos extraíbles para trasladar dicha información. Asimismo tu organización decide migrar hacia tecnología inalámbrica, ergo: debes configurar el kernel para adicionar el soporte del chipset de tu tarjeta inalámbrica; esto porque tuviste la mala suerte de que por defecto Linux no lo incluía.

Básicamente lo que debes hacer es crear un paquete (por ser paquete: fácil distribución, instalación y purgado) con el kernel de Debian optimizado: deshabilitando los puertos USB y agregando el módulo que ofrece soporte a tu tarjeta inalámbrica.

El problema radica en que tu organización posee 1200 usuarios (cada uno con su máquina), sería poco práctico y absurdo enviar el grupo de soporte a realizar el proceso de compilación máquina por máquina. Pero como tú eres buen administrador de red: tienes un mirror de Debian personalizado donde subes paquetes desarrollados o modificados por ti (o por tu grupo de administración/soporte de sistemas). Así te motivas a compilar dicho kernel optimizado y lo subes al mirror. Para garantizar la convergencia de dicho kernel en todas las máquinas utilizas herramientas como cfengine, puppet y pkgsync.

Si tienes curiosidad de como hacer ese mirror personalizado: busca información sobre reprepro.

Descargando y desempaquetando el kernel

En principio, para compilar un kernel es evidente que debes descargar el código fuente del mismo. Para eso ingresamos en la página oficial del proyecto donde se encuentran todos los kernel oficiales de Linux, desde la primera versión hasta la última. Cuando los descarguemos vendrá empaquetado y comprimido en alguno de los siguientes formatos: .tar.bz2 o .tar.gz . Es indiferente cual se descarguen, explicaré como descomprimir y desempaquetar ambos tipos de formato.

Lo tradicional es descomprimir el kernel en el directorio /usr/src, sin embargo no olvides que tienes la libertad de hacerlo en donde caprichosamente desees. En el momento de escruales módulos deseamos que tenga (o que no tenga) una vez compilado. Como es característico del Software Libre: tenemos varias maneras de hacer las cosas, hablemos sobre 3 formas de configurar el kernel:

1era alternativa: make config <-- Hay que tener algo de experiencia, si no la tienes no te recomiendo seguir este camino ya que hace muchas preguntas de hardware.

2da alternativa: make menuconfig <-- Es muy cómodo hacer la configuración por este método porque posees un menú muy sencillo he interactivo. NOTA: Necesitas tener instalado las las librerías ncurses, en debian: aptitude install libncurses5-dev

3ra alternativa: make xconfig <-- Debes tener instalado y en funcionamiento el servidor X, ya que toda la configuración se hace gráficamente (haciendo uso del sistema de ventanas). NOTA: Necesitas tener instaladas las librerías QT, en debian aptitude install libqt3-dev

Para la configuración utilizaré la segunda alternativa, es decir, make menuconfig, como lo hago siempre. Estás en la libertad de utilizar la que quieras. Sin embargo te recomiendo el segundo método debido a que no necesitas estar en entornos de escritorio ni tener funcionando el servidor X, además que tiene una interfaz muy simple e interactiva.

Para comenzar la configuración:

make menuconfig

Cuando se dediquen a configurar el kernel recuerden ser muy precavidos seleccionando o habilitando los módulos. Si tenemos dispositivos como FlashDrive (o Pendrive) es indefectible activar el soporte SCSI (específicamente soporte para discos SCSI), ya que estos son emulados como discos SCSI en Linux. Si desactivas el soporte para CDROM, evidentemente la unidad de CDROM no funcionaría una vez instalado. De igual manera pasa si desactivamos el soporte USB, no funcionaría todo los que conectemos por el puerto USB.

  1. Compilando

Terminada la configuración del kernel lo compilaremos. Debido a que lo estamos haciendo a la Debian way es necesario que tengamos instalado un paquete llamado kernel-package, el cual suministrará las herramientas necesarias para poder compilar y generar el paquete con nuestro kernel, para instalarla: aptitude install kernel-package. Antes de comenzar la compilación debemos estar en el directorio donde se encuentra el código fuente del kernel y luego ejecutar lo siguiente:

make-kpkg clean

make-kpkg --initrd kernel_image kernel_headers

Los que hayan compilado un kernel de Linux este comando equivale a: make dep, make clean, make bzImage y make modules

La opción --initrd crea una imagen initrd en el paquete que se guardará en /boot cuando instalemos el kernel (recordar que solo estamos compilando y empaquetando, no instalando).

El comando anterior creará dos paquetes con extensión .deb en el directorio superior. Un paquete será el kernel y el otro los kernel-headers.

La opción de kernel_headers es opcional, yo la utilizo debido a que muchos programas y módulos (ver la sección Gestión de módulos) necesitan tener los headers del kernel que se está usando para poder ser instalados, ejemplo: el driver de nvidia, VMware, ndiswrapper, madwifi, otros.

NOTA: El tiempo de compilación es proporcional a la configuración que hayas hecho y a tu poder de computo. Si incluiste muchjos módulos se demorará más. Hay que tener paciencia, es muy frecuente que se tarde bastante.

Instalándolo

Una vez que termina la compilación y es corroborada la existencia de los dos paquetes en el directorio superior es el momento de instalarlo. La instalación es muy trivial, debemos ejecutar en el directorio donde están los paquetes:

dpkg -i TU_KERNEL.deb
dpkg -i TU_KERNEL-HEADERS.deb

Por ejemplo, en mi caso fue así:

dpkg -i kernel-image-2.6.15_10.00.Custom_i386.deb
dpkg -i kernel-headers-2.6.15_10.00.Custom_i386.deb

¡Felicitaciones! Con esto terminas la instalación del kernel, ya podrías reiniciar la máquina e iniciar con tu nuevo kernel.

Gestionando módulos

Module Assistant - Compilando y agregando módulos

Module Assistant es una herramienta para la gestión de módulos ya empaquetados (preparadas suiciar el computadora):

m-a install madwifi

Con esto ya tienes el módulo instalado y listo para funcionar funcionar. El último comando lo que hace es instalar el paquete .deb al que hicimos referencia anteriormente.

Ya el módulo está instalado, faltaría cargarlo (en la mayoría de los sistemas de carga al conectar la tarjeta):

modprobe ath_pci

Consulta la sección de tips para encontrar una manera mas resumida de ejecutar todos estos pasos ;-)

Módulos no preparados para Debian

Es muy probable que en la sección anterior se hayan preguntado que hacer con los módulos no preparados para debian: si hay solución para ellos, sólo que es un poco más laboriosa y tedioso el proceso. De igual manera tomaré un ejemplo para explicar los pasos a seguir.

Hace unos meses publicaron un exploit que permitía a cualquier usuario del sistema obtener privilegios de administración (root). Como es característico de la mayoría de las aplicaciones de gran envergadura en el ámbito de Software libre, el parche para corregir esta vulnerabilidad se desarrolló prácticamente enseguida. El exploit se llama "vmsplice" y el parche (era un módulo realmente) consistía en un módulo que cargabas que impedía el funcionamiento del exploit.

Aplicar parches al kernel

Para aplicar un parche hacemos uso del programa patch. Es probable que lo tengamos instalado, de no ser así:

aptitude install patch

Una vez instalado se puede aplicar el parche distintas formas:

A la manera Debian

Una vez descargado el parche (normalmente un archivo .patch) lo copiamos al directorio donde están las fuentes del kernel (depende donde no los hayamos descargado, siguiendo el tutorial: /usr/src/linux-version) y al compilarlo agregar:

make-kpkg --initrd --added-patches=MI-PARCHE.patch kernel_image kernel_headers

make-kpkg se encargará de aplicar el parche y compilar nuevamente el kernel, notar que es le mismo comando (make-kpkg) que hemos venido usando a lo largo del tutorial. Adjunto al argumento --added-patches= deberás colocar, separado por comas, los parches a aplicar al kernea compilación para identificar al paquete .deb en el directorio superior. Para hacer esto necesitas agregar --append-to-version=NOMBRE. Como ya se imaginan, donde dice nombre es donde colocan el nombre que caracterice a cada kernel.

  • ¿Quieres ejecutar con un solo comando todos los pasos para tener en funcionamiento un módulo con Module Assistant? Pues el truco es ejecutar:

    m-a a-i madwifi

    a-i Significa auto-install, equivale a prepare,build e install

  • Si tenías un kernel con módulos ya instalados (por ejemplo, madwifi, nvidia, etc) e instalas un nuevo kernel perderás el soporte de estos módulos en tu nuevo kernel. Ergo: tienes que volver a compilarlos, no es tan tráfico porque afortunadamente tienes la herramienta Module Assitant

  • Recuerda que no estás vetado de google. Si se presenta algún problema: www.google.com

Copyrigth y licencia

Copyright (c) 2006 Alejandro Garrido Mota.

Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".

1ra edición. Versión 1.0: 15 Junio del 2006 2da edición. Versión 1.3: Mejorado y actualizado el artículo. 28 de noviembre del 2006 3ra edición. Versión-1.4: Agregando información acerca de Gestión de módulos y parches. 4 Febrero del 2008