Product SiteDocumentation Site

8.10. Compilación de un núcleo

El núcleo que provee Debian incluye la mayor cantidad de funcionalidad posible así como también la mayor cantidad de controladores para cubrir el espectro más amplio de configuraciones de hardware. Es por esto que algunos usuarios prefieren compilar el núcleo para incluir sólamente lo que necesiten específicamente. Hay dos razones para esta elección. Primero, podría optimizar el consumo de memoria ya que el código del núcleo, aún cuando no sea utilizado, ocupa memoria por nada (y nunca es «bajado» al espacio de swap ya que utiliza RAM real) lo que puede disminuir el rendimiento general del sistema. Un núcleo compilado localmente también puede limitar el riesgo de problemas de seguridad ya que sólo se compila y ejecuta una fracción del código del núcleo.
Necesita además recompilar el núcleo si desea utilizar ciertas funcionalidades que sólo están disponibles como parches (y no están incluidas en la versión estándar del núcleo).

8.10.1. Introducción y prerequisitos

No es sorprendete que Debian administre el núcleo como un paquete, que no es la forma tradicional en la que se compilan e instalan núcleos. Debido a que el núcleo se mantiene bajo el control del sistema de paquetes puede ser eliminado limpiamente o desplegado en varias máquinas. Lo que es más, los scripts asociados con estos paquetes automatizan la interacción con el gestor de arranque y el generador de initrd.
Las fuenes de Linux en origen contienen todo lo necesario para crear el paquete Debian del núcleo. Sin embargo, necesitará instalar build-essential para asegurarse que posee las herramientas necesarias para crear un paquete Debian. Lo que es más, el paso de configuración para el núcleo necesita el paquete libncurses5-dev (antes libncurses5-dev, que es ahora un paquete de transición). Finalmente, el paquete fakeroot le permitirá crear el paquete Debian sin utilizar permisos de administrador.

8.10.2. Obtención de las fuentes

Como cualquier cosa que pueda ser útil en un sistema Debian, las fuentes del núcleo Linux están disponibles en un paquete. Para obtenerlas simplemente instale el paquete linux-source-versión. Puede ver las diferentes versiones del núcleo empaquetados por Debian con apt search ^linux-source. La última versión está disponible en la distribución Unstable: puede conseguirlas sin demasiado riesgo (especialmente si tiene configurado APT según las instrucciones de la Sección 6.2.6, “Trabajo con varias distribuciones”). Sepa que el código fuente que contienen estos paquetes no corresponde exactamente con lo publicado por Linus Torvalds y los desarrolladores del núcleo; como todas las distribuciones, Debian aplica una serie de parches, que pueden (o no) ser incluídas en la versión de origen de Linux. Estas modificaciones incluyen retroadaptaciones de correcciones/funcionalidades/controladores de nuevas versiones del núcleo, funcionalidades que no están (completamente) incluídas en el árbol de origen de Linux e inclusive a veces cambios específicos para Debian.
El resto de esta sección se concentra en la versión 5.10 del núcleo Linux pero los ejemplos pueden, obviamente, adaptarse a la versión particular del núcleo que desee.
Asumimos que instaló el paquete linux-source-5.10. Contiene /usr/src/linux-source-5.10.tar.xz, un archivo comprimido de las fuentes del núcleo. Debe extraer estos archivos en un nuevo directorio (no directamente bajo /usr/src/ ya que no necesita permisos especiales para compilar un núcleo Linux): ~/kernel/ es apropiado.
$ mkdir ~/kernel; cd ~/kernel
$ tar -xaf /usr/src/linux-source-5.10.tar.xz
Para construir un kernel a partir de las fuentes prístinas, simplemente descargue el tarball de la versión de su elección desde kernel.org, verifique la integridad después de importar la clave de los mantenedores del kernel, y luego proceda como se describe en los siguientes capítulos-

$ wget https://kernel.org/pub/linux/kernel/v5.x/linux-5.10.62.tar.xz
[..]
$ wget https://kernel.org/pub/linux/kernel/v5.x/linux-5.10.62.tar.sign
[..]
$ unxz -c linux-5.10.62.tar.xz | gpg --verify linux-5.10.62.tar.sign -
gpg: Firma hecha el vie 03 Sep 2021 10:11:35 AM CEST
gpg:                con clave RSA 647F28654894E3BD457199BE38DBBDC86092693E
gpg: Buena firma desde "Greg Kroah-Hartman <gregkh@linuxfoundation.org>" [unknown]
gpg:                 aka "Greg Kroah-Hartman (Linux kernel stable release signing key) <greg@kroah.com>" [unknown]
gpg:                 aka "Greg Kroah-Hartman <gregkh@kernel.org>" [unknown]
gpg: ATENCIÓN: ¡Esta clave no está certificada con una firma de confianza!
gpg:          No hay indicios de que la firma pertenezca al propietario.
Huella de clave primaria: 647F 2865 4894 E3BD 4571  99BE 38DB BDC8 6092 693E

8.10.3. Configuración del núcleo

El siguiente paso consiste en configurar el núcleo según sus necesidades. El procedimiento exacto depende de los objetivos.
Al recompilar una versión más reciente del núcleo (posiblemente con un parche adicional), probablemente mantenga la configuración tan parecida a la propuesta por Debian como le sea posible. En este caso, y en lugar de reconfigurar todo desde cero, es suficiente copiar el archivo /boot/config-versión (la versión es la del núcleo utilizado actualmente, que puede encontrarse con uname -r) en un archivo .config en el directorio que contenga las fuentes del núcleo. Asegúrese de leer sidebar TIP Falta debian/certs/debian-uefi-certs.pem en este caso.
$ cp /boot/config-5.10.0-8-amd64 ~/kernel/linux-source-5.10/.config
A menos que necesite cambiar la configuración, puede parar aquí y continua en Sección 8.10.4, “Compilación y creación del paquete”. Si, por el otro lado, necesita cambiarla o si decide reconfigurar todo desde cero, debe tomarse el tiempo de configurar su núcleo. Hay varias interfaces dedicadas en el directorio de fuentes del núcleo que puede utilizar ejecutando make objetivo donde objetivo es uno de los valores descriptos a continuación.
make menuconfig compila y ejecuta una interfaz en modo texto (aquí es donde necesita el paquete libncurses5-dev) que permite navegar entre las opciones disponibles en una estructura jerárquica. Pulsar la tecla Espacio cambia el valor de la opción seleccionada y Enter valida el botón seleccionado al pie de la pantalla; Seleccionar vuelve al submenú seleccionado; Salir cierra la pantalla actual y vuelve un paso atrás en la jerarquía; Ayuda mostrará información más detallada sobre el comportamiento de la opción seleccionada. Las flechas del cursor permiten moverse en la lista de opciones y botones. Para salir del programa de configuración, seleccionar Salir del menú principal. El programa luego ofrece guardar los cambios que realizó; acéptar si se está satisfecho con lo seleccionado.
Otras interfaces tienen funcionalidades similares pero trabajan con interfaces gráficas más modernas; como make xconfig que utiliza una interfaz gráfica Qt y make gconfig que utiliza GTK+. La primera necesita el paquete qtbase5-dev mientras que la última depende de los paquetes libglade2-dev y libgtk2.0-dev.
Cuando utiliza una de las interfaces de configuración, siempre es buena idea comenzar desde una configuración predeterminada razonable. El núcleo provee tales configuraciones en arch/arquitectura/configs/*_defconfig y puede mover la configuración que desee si ejecuta algo similar a make x86_64_defconfig (en el caso de un equipo de 64 bits) o make i386_defconfig (en el caso de un equipo de 32 bits).

8.10.4. Compilación y creación del paquete

Una vez que la configuración del núcleo está lista, un simple make deb-pkg generará hasta 5 paquetes Debian:
linux-image-versión
contiene la imagen del núcleo y los módulos asociados,
linux-headers-versión
contiene los archivos de cabecera necesarios para crear módulos externos,
linux-firmware-image-versión
contiene los archivos de firmware necesarios para algunos controladores (este paquete podría faltar cuando construya desde las fuentes del núcleo proporcionadas por Debian),
linux-image-versión-dbg
contiene los símbolos de depuración para la imagen del núcleo y sus módulos (sólo se crea si CONFIG_DEBUG_INFO=y), y
linux-libc-dev
contiene encabezados relevantes para algunas bibliotecas del espacio-usuario como GNU glibc.
La cadena versión es la concatenación de la versión de origen (definida por las variables VERSION, PATCHLEVEL, SUBLEVEL y EXTRAVERSION en el Makefile), del parámetro de configuración LOCALVERSION y la variable de entorno LOCALVERSION. La versión del paquete reutiliza la misma cadena de versión con una revisión adicional que generalmente aumenta (y se almacena en .version), excepto si la previene con la variable de entorno KDEB_PKGVERSION.
$ make deb-pkg LOCALVERSION=-falcot KDEB_PKGVERSION=$(make kernelversion)-1
[...]
$ ls ../*.deb
../linux-headers-5.10.46-falcot_5.10.46-1_amd64.deb
../linux-image-5.10.46-falcot_5.10.46-1_amd64.deb
../linux-image-5.10.46-falcot-dbg_5.10.46-1_amd64.deb
../linux-libc-dev_5.10.46-1_amd64.deb
Todo el proceso requiere unos 20 GB de espacio libre, al menos 8 GB de RAM y varias horas de compilación (utilizando un núcleo) para un núcleo Debian amd64 estándar. Estos requisitos se pueden reducir drásticamente deshabilitando la información de depuración usando CONFIG_DEBUG_INFO=n, pero esto hará imposible rastrear errores del kernel ("ups") usando gdb y también detendrá la creación del paquetelinux-image-version-dbg.

8.10.5. Compilación de módulos externos

Se mantienen algunos módulos fuera del núcleo Linux oficial. Para utilizarlos debe compilarlos junto al núcleo correspondiente. Debian provee algunos módulos de terceros comunes en paquetes dedicados, como vpb-driver-source (módulos adicionales extra para el hardware de telefonía Voicetronix) o oss4-source (controlador de placas PCEngines ALIX 2/3).
Estos paquetes son muchos y variados, apt-cache rdepends module-assistant$ puede mostrar la lista proporcionada por Debian. Sin embargo, una lista completa no es muy útil ya que no hay una razón particular para compilar módulos externos a menos que sepa que los necesita. En estos casos, la documentación del dispositivo típicamente detallará el o los módulos específicos que necesita para funcionar bajo Linux.
Veamos, por ejemplo, el paquete dahdi-source: luego de instalarlo podrá encontrar un compendio .tar.bz2 de las fuentes del módulo en /usr/src/. Si bien podríamos extraer manualmente el archivo y compilar el módulo, en la práctica preferimos automatizarlo con DKMS (Dynamic Kernel Module Support). La mayoría de los módulos ofrecen la integración necesaria con DKMS en un paquete que finaliza con el sufijo -dkms. En nuestro caso, sólo necesitamos instalar el paquete dahdi-dkms para compilar el módulo del núcleo para el núcleo actual, siempre que esté instalado el paquete linux-headers-* que coincida con el núcleo instalado. Por ejemplo, si utiliza linux-image-amd64 debería instalar también linux-headers-amd64.
$ sudo apt install dahdi-dkms
[...]
Setting up dkms (2.8.4-3) ...
Setting up linux-headers-5.10.0-8-amd64 (5.10.46-4) ...
/etc/kernel/header_postinst.d/dkms:
dkms: running auto installation service for kernel 5.10.0-8-amd64:.
Setting up dahdi-dkms (1:2.11.1.0.20170917~dfsg-7.4) ...
Loading new dahdi-2.11.1.0.20170917~dfsg-7.4 DKMS files...
Building for 5.10.0-8-amd64
Building initial module for 5.10.0-8-amd64
Done.

dahdi_dummy.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/5.10.0-8-amd64/updates/dkms/

dahdi_dynamic_eth.ko:
Running module version sanity check.
 - Original module
   - No original module exists within this kernel
 - Installation
   - Installing to /lib/modules/5.10.0-8-amd64/updates/dkms/

[...]
DKMS: install completed.
$ sudo dkms status
dahdi, 2.11.1.0.20170917~dfsg-7.4, 5.10.0-8-amd64, x86_64: installed
$ sudo modinfo dahdi_dummy
filename:       /lib/modules/5.10.0-8-amd64/updates/dkms/dahdi_dummy.ko
license:        GPL v2
author:         Robert Pleh <robert.pleh@hermes.si>
description:    Timing-Only Driver
depends:        dahdi
retpoline:      Y
name:           dahdi_dummy
vermagic:       5.10.0-8-amd64 SMP mod_unload modversions 
parm:           debug:int

8.10.6. Aplicación de un parche al núcleo

Algunas funcionalidades no están incluidas en el núcleo estándar debido a falta de madurez o algún desacuerdo con los encargados del núcleo. Dichas funcionalidades pueden ser distribuidas como parches que cualquiera puede aplicar a las fuentes del núcleo.
Debian a veces proporciona algunos de estos parches en paquetes linux-patch-*, pero a veces no llegan a las publicaciones estables (a veces por las mismas razones por las que no son fusionados en el repositorio oficial del núcleo). Estos paquetes instalan archivos en el directorio /usr/src/kernel-patches/.
Para aplicar uno o más de estos parches instalados, utilice el programa patch en el directorio con las fuentes y luego inicie la compilación del núcleo como ya describimos. A continuación se muestra un ejemplo antiguo usando linux-patch-grsecurity2 and linux-source-4.9.
$ cd ~/kernel/linux-source-4.9
$ make clean
$ zcat /usr/src/kernel-patches/diffs/grsecurity2/grsecurity-3.1-4.9.11-201702181444.patch.gz | patch -p1
Sepa que un parche dado no necesariamente funcionará con toda versión del núcleo; es posible que patch falle al aplicarlo en las fuentes del núcleo. Se mostrará un mensaje de error que provee algunos detalles del fallo; en este caso, revise la documentación disponible en el paquete Debian del parche (en el directorio /usr/share/doc/linux-patch-*/). En la mayoría de los casos, el desarrollador indica para qué versiones del núcleo está creado el parche.