sábado, 30 de marzo de 2013

Compilando un kernel custom para Linux


 El otro día necesitaba aplicar un patch al kernel de Ubuntu. Nunca me había tocado hacer esto así que no tuve más remedio que aprender :)

Con una búsqueda en Google podemos encontrar decenas de tutoriales, desde avanzados hasta novatos. En particular, yo seguí este tutorial pero tuve que hacer algunas modificaciones.

Aclaro que, en mi caso, estaba trabajando con kernel 3.0.0-12.20:


Lo primero que tenemos que hacer es instalar algunos paquetes que vamos a necesitar para compilar:
sudo apt-get install gcc fakeroot kernel-package libncurses5-devel
Luego, vamos a necesitar los sources del kernel. Acá tenemos un par de opciones para poder obtenerlos:

1. Podemos ejecutar el siguiente comando: apt-get source linux-image-$(uname -r)

De esta manera, vamos a conseguir los sources de kernel up-to-date (incluyendo parches de seguridad) para la versión de kernel que tenemos actualmente instalada.
 
En este caso, yo quería que esos parches no estén así que recurrí a la segunda opción.

2. Desde Linux Kernel Archives podemos acceder a todas las versiones del kernel de Linux.

3. En mi caso, accedí directamente al repositorio de paquetes de Ubuntu y elegí la versión que estaba utilizando (oneric) y luego en la sección de "admin" conseguí lo que buscaba linux-image-3.0.0-12-generic (3.0.0-12.20)



Sobre la parte derecha de su pantalla, van a poder observar un par de links para bajarse unos archivos:



De ahí nos vamos a bajar los siguientes archivos:
1. linux_3.0.0.orig.tar.gz: los sources del kernel "pelados"
2- linux_3.0.0-12.20.diff.gz: parches
Una vez hecho eso, vamos al home y creamos una carpeta, por ejemplo, llamada src, de esta manera:


Y en dicha carpeta colocamos los dos archivos que acabamos de bajar y los descomprimimos:
nriva@ubuntu:~/src$ tar -xf linux_3.0.0.orig.tar.gz
nriva@ubuntu:~/src$ gunzip linux_3.0.0-12.20.diff.gz
Por una lado tenemos la carpeta con los sources originales y por el otro un archivos .diff que contiene diferentes parches para dicho kernel. Por lo tanto, voy a aplicar dichos parches a los sources originales antes de hacer cualquier modificación.

Para aplicar los parches, debemos de ingresar a la carpeta donde se encuentran los sources originales y ejecutar el siguiente comando (deben de tener previamente instalado el programa "patch"):
nriva@ubuntu:~/src/linux-3.0$ patch -p1 < ../linux_3.0.0-12.20.diff
De esa manera, aplicamos los parches correspondientes al kernel original.

Una vez que tenemos hecho eso, podemos hacer los cambios que necesitemos en los sources y finalmente, compilar:

time fakeroot make-kpkg --initrd --append-to-version=-tweak kernel-image kernel-headers
El comando "time" no es necesario, es solo para ver cuando se demoró en terminar todo el proceso.

El comando "fakeroot" es una especie de falso sudo. Se utiliza cuando se necesita manipular archivos y crear, como en este caso, paquetes .deb.

make-kpkg se utiliza para crear paquetes .deb pero relacionados con el kernel.

Con "--initrd" se crea una especie de filesystem temporal (RAM disk) necesario durante el booteo del nuevo kernel.

El parámetro "--append-to-version" sirve para poder agregar una especie de "postfijo" al nuevo kernel que se generará. En este caso será algo como "kernel 3.0.0-12-tweak".

Finalmente, le indicamos que genere los binarios y headers para nuestro kernel.

Una vez que termine el proceso, vamos a tener algo como esto:

make[2]: Leaving directory `/home/nriva/src/linux-3.0'
make[1]: Leaving directory `/home/nriva/src/linux-3.0'

real    126m19.925s
user    81m21.793s
sys    14m1.429s
nriva@ubuntu:~/src/linux-3.0$
Al ir un nivel más arriba del directorio en el cual nos encontramos, vamos a encontrar dos archivos .deb:

 
Los archivos son los siguientes:
linux-image-3.0.4-tweak_3.0.4-tweak-10.00.Custom_amd64.deb
linux-headers-3.0.4-tweak_3.0.4-tweak-10.00.Custom_amd64.deb
Lo que debemos de hacer ahora es instalar ambos paquetes, de la siguiente manera:
sudo dpkg -i linux-image-3.0.4-tweak_3.0.4-tweak-10.00.Custom_amd64.deb
Deberían de tener un output como este:
nriva@ubuntu:~/src$ sudo dpkg -i linux-image-3.0.4-tweak_3.0.4-tweak-10.00.Custom_amd64.deb
[sudo] password for nriva:
Selecting previously deselected package linux-image-3.0.4-tweak.
(Reading database ... 127324 files and directories currently installed.)
Unpacking linux-image-3.0.4-tweak (from linux-image-3.0.4-tweak_3.0.4-tweak-10.00.Custom_amd64.deb) ...
Done.
Setting up linux-image-3.0.4-tweak (3.0.4-tweak-10.00.Custom) ...
Running depmod.
Examining /etc/kernel/postinst.d.
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 3.0.4-tweak /boot/vmlinuz-3.0.4-tweak
update-initramfs: Generating /boot/initrd.img-3.0.4-tweak
run-parts: executing /etc/kernel/postinst.d/pm-utils 3.0.4-tweak /boot/vmlinuz-3.0.4-tweak
run-parts: executing /etc/kernel/postinst.d/update-notifier 3.0.4-tweak /boot/vmlinuz-3.0.4-tweak
run-parts: executing /etc/kernel/postinst.d/zz-update-grub 3.0.4-tweak /boot/vmlinuz-3.0.4-tweak
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-3.0.4-tweak
Found initrd image: /boot/initrd.img-3.0.4-tweak
Found linux image: /boot/vmlinuz-3.0.0-12-generic
Found initrd image: /boot/initrd.img-3.0.0-12-generic
Found memtest86+ image: /boot/memtest86+.bin
done

 Ahora, instalamos los headers:
nriva@ubuntu:~/src$ sudo dpkg -i linux-headers-3.0.4-tweak_3.0.4-tweak-10.00.Custom_amd64.deb
Y el output es el siguiente:
nriva@ubuntu:~/src$ sudo dpkg -i linux-headers-3.0.4-tweak_3.0.4-tweak-10.00.Custom_amd64.deb
[sudo] password for nriva:
Selecting previously deselected package linux-headers-3.0.4-tweak.
(Reading database ... 131337 files and directories currently installed.)
Unpacking linux-headers-3.0.4-tweak (from linux-headers-3.0.4-tweak_3.0.4-tweak-10.00.Custom_amd64.deb) ...
Setting up linux-headers-3.0.4-tweak (3.0.4-tweak-10.00.Custom) ...
Examining /etc/kernel/header_postinst.d.

Ahora, solo rebooteamos y deberíamos de arrancar con el nuevo kernel por default. 

Para verificar que estamos corriendo con el nuevo kernel, abrimos una terminal y ejecutamos el comando: "uname -r":

 

Puede ocurrir que cuando booten el nuevo kernel se encuentren con un mensaje como este:
Kernel Panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
Eso lo pueden solucionar ejecutando los siguientes comandos:
sudo update-initramfs -u -k 3.0.4-tweak
sudo update-grub
En mi caso, compile varios kernels en la misma distro y quería bootear con uno u otro según las pruebas que tenía que hacer. Para eso, tuve que configurar grub para que me de la lista de kernels al inicio. Hay varias maneras de hacer esto, pero la que me funcionó fue la de comentar las siguientes líneas en /etc/default/grub:
#GRUB_HIDDEN_TIMEOUT=0
#GRUB_HIDDEN_TIMEOUT_QUIET=true
Recuerden de ejecutar "sudo update-grub" después de modificar el archivo de configuración de grub.

Otra cosa que también necesitaba era remover kernels que ya no necesitaba, eso lo podemos hacer ejecutando los siguiente comandos resaltados en amarillo:
nriva@ubuntu:~$ dpkg --list | grep linux-image
ii  linux-image-3.0.0-12-generic           3.0.0-12.20                             Linux kernel image for version 3.0.0 on x86/x86_64
ii  linux-image-3.0.4-tweak                3.0.4-tweak-10.00.Custom                Linux kernel binary image for version 3.0.4-tweak
ii  linux-image-generic                    3.0.0.12.14                             Generic Linux kernel image
nriva@ubuntu:~$ sudo apt-get purge linux-image-3.0.4-tweak
Eso es todo!. Hasta pronto!.

Referencias:

No hay comentarios: