…esto no es un subtítulo…
2026-05-09
Nos topamos con una vulnerabilidad del núcleo Linux que permitía el escalado de privilegios y que afectaba a varios equipos. La información sobre la vulnerabilidad que podíamos encontrar en línea indicaba que la vulnerabilidad estaba en el controlador de RxRPC, un protocolo que se usa el sistema de ficheros AFS, algo que no utilizamos. A falta de algo mejor, siempre podíamos evitar la carga del controlador problemático, llamado rxrpc.
En el momento en el que nos llegó la noticia de la vulnerabilidad, la documentación en línea sugería evitar que modprobe cargara el módulo rxrpc, pero nos encontramos con que, en el caso teníamos entre manos, el controlador no estaba en forma de módulo, sino ya incluido en el núcleo («built-in»). Había que idear otra solución.
Por fortuna, es posible impedir el arranque de un controlador independientemente de si va en forma de módulo o está directamente incluido («built-in») en el núcleo. Cada controlador tiene una función de inicio que sirve para cargarlo y basta con pasar al núcleo la lista de funciones de inicio cuya ejecución prohibimos con el argumento initcall_blacklist. Por ejemplo, si quisiéramos prohibir la ejecución de las funciones gato_init y perro_init, que servirían para el inicio de los controladores gato y perro, podríamos incluir lo siguiente entre los argumentos que el cargador de arranque le pasa al núcleo: initcall_blacklist=gato_init,perro_init.
Solamente teníamos que encontrar cuál es la función de inicio del controlador rxrpc. Por supuesto, no es rxrpc_init.
Podríamos haber buscado en montañas de documentación cuál es la función de inicio del controlador rxrpc, pero decidimos ir a lo bruto y mirar el código fuente del núcleo Linux. Dicho y hecho: descargamos de kernel.org el tarball correspondiente y nos arremangamos.
Lo que sabíamos era que el controlador rxrpc tiene que aparecer mencionado en algún Makefile de forma similar a la siguiente:
obj-$(CONFIG_EL_NOMBRE_DE_ALGUNA_OPCIÓN) += rxrpc.o
Efectivamente, en net/rxrpc/Makefile estaba la siguiente línea:
obj-$(CONFIG_AF_RXRPC) += rxrpc.o
También había una variable, rxrpc-y, con todos los objetos correspondientes a rxrpc: af_rxrpc.o, call_accept.o, call_event.o…, correspondientes al código fuente af_rxrpc.c, call_accept.c, call_event.c… En alguno tenía que haber una línea similar a la siguiente:
module_init(FUNCIÓN_DE_INICIO_QUE_HAY_QUE_BLOQUEAR)
El tesoro estaba justo en el primer fichero, af_rxrpc.c:
module_init(af_rxrpc_init);
Así que la función a bloquear era af_rxrpc_init.
También pudimos verificar que estábamos mirando donde corresponde. Para empezar, en af_rxrpc.c estaba lo siguiente:
MODULE_DESCRIPTION("RxRPC network protocol");
Además de rxrpc, también había problemas con esp4 y esp6, que tienen que ver con IPsec, pero que no usábamos en las máquinas afectadas. Acabamos pasándole el siguiente argumento al núcleo durante el arranque:
initcall_blacklist=esp4_init,esp6_init,af_rxrpc_init
Con esto, pudimos comprobar que ya no éramos vulnerables y podíamos esperar con calma una actualización del núcleo que corrigiera el problema de forma definitiva.
Categorías: Informática