Kees Cook introdujo nuevos parches para mejorar la seguridad de pila del kernel de Linux
Kees Cook, un antiguo administrador de sistemas en jefe de kernel.org y líder del equipo de seguridad de Ubuntu, que ahora trabaja en Google para proteger Android y ChromeOS, ha publicado un conjunto de parches que aleatorizan las compensaciones de la pila del kernel al manejar las llamadas al sistema. Los parches mejoran la seguridad del kernel al cambiar la ubicación de la pila, lo que hace que los ataques de pila sean mucho más difíciles y menos exitosos
La idea original del parche pertenece al proyecto PaX RANDKSTACK. En 2019, Elena Reshetova, ingeniera de Intel, intentó crear una implementación de esta idea, adecuada para su inclusión en la composición principal del kernel de Linux.
Posteriormente, la iniciativa fue tomada por Kees Cook quien presentó una implementación adecuada para la versión principal del kernel y cuyos parches están previstos para la versión 5.13 de Linux.
El modo estará deshabilitado de forma predeterminada y para habilitarlo, se ofrecen el parámetro de línea de comando del kernel «randomize_kstack_offset = on/off» y la configuración CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT, además de que la sobrecarga de habilitar el modo se estima en aproximadamente un 1% de pérdida de rendimiento.
La esencia de la protección propuesta es elegir un desplazamiento de pila aleatorio en cada llamada al sistema, lo que complica la determinación del diseño de la pila en la memoria incluso si se recibe información sobre las direcciones, ya que la dirección base de la pila cambiará en el siguiente llamada.
A diferencia de la implementación de PaX RANDKSTACK, en los parches propuestos para su inclusión en el kernel, la aleatorización no se realiza en la etapa inicial, sino después de establecer la estructura pt_regs, lo que hace que sea imposible utilizar métodos basados en ptrace para determinar un desplazamiento aleatorio durante una llamada al sistema de larga duración.
Como las protecciones de la pila del kernel de Linux han mejorado constantemente (asignación de pila basada en vmap con páginas de protección, eliminación de thread_info, STACKLEAK), los atacantes han tenido que encontrar nuevas formas para que sus exploits funcionen.
Lo han hecho, y continúan confiando en el determinismo de la pila del kernel, en situaciones en las que VMAP_STACK y THREAD_INFO_IN_TASK_STRUCT no eran relevantes. Por ejemplo, los siguientes ataques recientes se habrían visto obstaculizados si el desplazamiento de la pila no fuera determinista entre llamadas al sistema
El objetivo de la función randomize_kstack_offset es agregar un desplazamiento aleatorio después de que pt_regs se haya enviado a la pila y antes de que el resto de la pila de subprocesos se use durante el procesamiento de la llamada al sistema, y cambiarlo cada vez que un proceso emite una llamada al sistema. La fuente de aleatoriedad está actualmente definida por la arquitectura (pero x86 usa el byte bajo de rdtsc ()).
Es posible realizar mejoras futuras para diferentes fuentes de entropía, pero fuera del alcance de este parche. Además, para agregar más imprevisibilidad, se eligen nuevas compensaciones al final de las llamadas al sistema (el tiempo de las cuales debería ser menos fácil de medir desde el espacio de usuario que en el momento de la entrada de la llamada al sistema) y se almacenan en una variable por CPU, de modo que la vida del valor no permanece explícitamente ligado a una sola tarea.
No hay cambios visibles para esto en x86 porque el protector de pila ya está deshabilitado incondicionalmente para la unidad de compilación, pero el cambio es necesario en arm64. Desafortunadamente, no hay ningún atributo que pueda usarse para deshabilitar el protector de pila para funciones específicas. Comparación con la función PaX RANDKSTACK: La función RANDKSTACK aleatoriza la ubicación del inicio de la pila (cpu_current_top_of_stack), es decir, incluye la ubicación de la estructura pt_regs en la pila.
Inicialmente, este parche siguió el mismo enfoque, pero durante las discusiones recientes, se ha determinado que tiene poco valor, ya que, si la funcionalidad ptrace está disponible para un atacante, puede usar PTRACE_PEEKUSR para leer/escribir diferentes compensaciones en la estructura pt_regs, observar el comportamiento de la caché de los accesos pt_regs y averiguar el desplazamiento de pila aleatorio.
Finalmente se menciona que la implementación inicial admite procesadores ARM64 y x86/x86_64.