Tutorial para desarrolladores: Live patching del núcleo Linux de Debian 10 con Kpatch
Live patching es un método para actualizar un kernel Linux sin reiniciar el kernel - y por lo tanto sin necesidad de reiniciar la máquina. Live patching se utiliza a menudo para parchear vulnerabilidades graves del núcleo Linux sin demora, porque live patching no causa interrupciones y no requiere una ventana de mantenimiento.
Existen algunas herramientas de parcheo en vivo y los usuarios del sistema operativo Debian a veces recurren a kpatch para implementar parches en vivo - o para ajustar el kernel.
Este tutorial es una demostración práctica de kpatch. Demostraremos cómo usar kpatch para cambiar el comportamiento de un núcleo Debian 10 en ejecución sin detenerlo, cambiando el contenido de /proc/uptime (y el uptime ) para que el tiempo de actividad del sistema sea 10 años mayor.
kpatch fue creado por Red Hat y funciona en Red Hat Enterprise Linux (RHEL) y sus derivados. Red Hat ofrece este servicio comercial de live patching para clientes de RHEL. En TuxCare, ofrecemos KernelCare Enterprise - que es capaz de parchear en vivo RHEL, así como cualquier otra distribución popular de Linux empresarial.
He elegido kpatch para este tutorial porque su código fuente está disponible gratuitamente y se actualiza con regularidad.
Requisitos previos
Estos son los requisitos previos del sistema para seguir este tutorial:
- Un sistema de prueba (no de producción) que ejecuta Debian Bullseye (para esta demostración se utilizó la versión 11.6) en una arquitectura x86_64/amd64
- 20 Gb de espacio libre en disco (el código fuente del núcleo de Linux ocupa unos 909 mb en disco, que aumentan a 17 gb cuando se compila).
- Su núcleo no ha sido personalizado; está utilizando el núcleo estándar suministrado por Debian.
- Su kernel tiene parcheado en vivo incorporado. Utilice este comando y espere ver dos valores establecidos en y para CONFIG_HAVE_LIVEPATCH y CONFIG_LIVEPATCH:
grep LIVEPATCH /boot/config-$(uname -r)
- La versión de gcc instalada coincide con la utilizada para compilar el núcleo original. (La versión kpatch-build fallará si las versiones no coinciden. Esto se puede anular con la opción -skip-gcc-checkaunque se desaconseja su uso).
- Para ver la versión de gcc instalada: gcc -version
- Para ver la versión de gcc utilizada para compilar el kernel actual: cat /proc/version
-
Instalar paquetes de dependencias
- Instalar y configurar sudo
En raíz:
apt-get install sudo (sudo should already be installed, but this makes sure of it) adduser <user> sudo
where <user> is the username for a normal user (all subsequent commands should be done as this user)
2.Instalar paquetes
3.sudo apt-get -y update
4.sudo apt-get -y upgrade
5.sudo apt-get -y install build-essential devscripts ccache gawk libelf-dev libssl-dev linux-source linux-image-$(uname -r)-dbg
-
Instalar kpatch
Como es común con los paquetes de Debian, hay un retraso entre las versiones actuales y las versiones ofrecidas como actualizaciones a través de apt regular. Tomemos el código más actual de kpatch y construyámoslo desde el código fuente.
git clone https://github.com/dynup/kpatch.git cd kpatch && make && sudo make install
-
Obtenga una copia del código fuente del núcleo de Linux
- (Opcional) Crear y mover a un directorio de trabajo
mkdir kernel && cd $_
- Extraer el código fuente del núcleo de Linux
tar xaf /usr/src/linux-source-5.10.tar.xz
Nota: 5.10 es la versión del núcleo Linux para Debian 11.6 en el momento de escribir este documento. Debería comprobar y sustituir la versión más reciente presente en /usr/src
-
Crear el archivo de configuración del núcleo Linux
- El núcleo de Linux se compila utilizando los parámetros de un archivo de configuración suministrado con su distribución. Haga una copia y cambie algunos parámetros para que kpatch-build pueda compilar un núcleo Linux con la misma configuración que su núcleo en ejecución.
- cd linux-source-5.10
cp /boot/config-$(uname -r) .config
- Compruebe que los ajustes necesarios del kernel están habilitados para utilizar kpatch. Todos deben devolver 'y'.
-
scripts/config -s DYNAMIC_FTRACE_WITH_REGS
-
scripts/config -s FUNCIÓN_TRACER
-
scripts/config -s HAVE_DYNAMIC_FTRACE_WITH_REGS
-
scripts/config -s TENER_FENTRÍA
-
scripts/config -s HAVE_LIVEPATCH
-
scripts/config -s KALLSYMS_ALL
-
scripts/config -s KALLSYMS_ALL
-
scripts/config -s LIVEPATCH
-
scripts/config -s MÓDULOS
-
scripts/config -s MÓDULO_SIG
-
scripts/config -s SYSFS
scripts/config -s SYSTEM_TRUSTED_KEYRING
- Cambiar el valor de un elemento de configuración del kernel
scripts/config --set-str SYSTEM_TRUSTED_KEYS ""
- Dejar el directorio fuente
cd .
-
Crear un parche
Un archivo fuente de parche es la salida del comando diff ejecutado en los archivos de código fuente original y modificado.
El ejemplo de aplicación de parches que se muestra en la sección "Inicio rápido" de la página de github de página de github de kpatch cambia la salida de /proc/meminfo. Muchos otros artículos de kpatch reproducen este ejemplo, así que yo quería algo diferente y un poco más interesante, aunque seguro.
Este ejemplo cambia la salida de tiempo de actividad para dar la ilusión de que el tiempo de actividad de su servidor ha aumentado en una década.
- Todavía en su directorio de trabajo, copie un archivo
cp linux-source-4.19/fs/proc/uptime.c .
- Edítalo. En la línea 33, cambia:
(unsigned long) uptime.tv_sec,
a
(unsigned long) uptime.tv_sec + 315576000,
Guardar el archivo
- Crear el archivo del parche
diff -u linux-source-5.10/fs/proc/uptime.c ./uptime.c > uptime.patch
- Cree el módulo del parche. (La primera vez que lo haga, tardará algún tiempo, ya que hay que compilar el código fuente del kernel. Las siguientes compilaciones son significativamente más rápidas, del orden de minutos. Esta es una de esas operaciones en las que lanzar más CPUs (virtuales) al problema ayudará a acelerar el proceso. Es una tarea limitada a la CPU).
kpatch-build -s linux-source-5.10 -v /usr/lib/debug/lib/modules/$(uname -r)/vmlinux uptime.patch
- Una vez hecho esto, tendrá un Módulo del núcleo cargable (.ko) para el parche
ls -l *.ko
-
Probar el parche
- Antes de cargar el módulo patch, compruebe el tiempo de actividad actual
cat /proc/uptime && uptime -p
- Cargar el módulo patch
sudo kpatch load livepatch-uptime.ko
- Compruebe de nuevo el tiempo de actividad
cat /proc/uptime && uptime -p
Debería ver que su tiempo de actividad es diez años mejor (el valor interno no ha cambiado, sólo lo que se imprime).
- Descargar el módulo patch
sudo kpatch unload livepatch-uptime.ko
- Compruebe que el tiempo de actividad ha vuelto a su valor anterior
cat /proc/uptime && uptime -p
Conclusión
Parchear en vivo el kernel de Linux con kpatch no es difícil. La dificultad reside en escribir un parche que no bloquee el sistema y que funcione con otros parches que vengan después. La mayoría de los parches se crean a partir de algo más que un simple diff y necesitan pruebas exhaustivas en múltiples versiones del núcleo ejecutadas en varias distribuciones.
Los redactores de parches deben ser tanto programadores expertos en C como desarrolladores experimentados del núcleo de Linux. Compilar el núcleo y probar los parches para cada versión requiere una gran inversión en hardware y herramientas de automatización.
La escasez de competencias y el coste de la infraestructura obligan a los proveedores a cobrar por los servicios de parcheo en directo, que a menudo se prestan a través de costosos programas de mantenimiento.
These charges add up to large sums, but that’s not the case with TuxCare’s live patching service – which starts from just $49.50/server/year for Linux. Click here to read more about TuxCare’s range of live patching services for the Linux kernel, databases, shared libraries, IoT devices, and virtualization systems.
Y no olvide leer nuestra guía explícita sobre Cómo aplicar los parches de seguridad del núcleo de Linux: 3 Maneras Diferentes. El artículo explica cómo actualizar los kernels de Linux sin reiniciar, cubriendo tres métodos diferentes para algunos de los kernels de Linux más populares.