La integridad del flujo de control (CFI) es un mecanismo de seguridad que no permite cambios en el gráfico del flujo de control original de un objeto binario compilado, lo que dificulta considerablemente que se produzcan ataques de ese tipo.
A partir de Android 9, puedes habilitar la CFI en el kernel.
El kernel de Linux tuvo dos implementaciones diferentes de CFI:
- Para Linux 6.0 y versiones anteriores, Clang CFI, que se basa en Clang LTO
- Para Linux 6.1 y versiones posteriores, Clang KCFI
La CFI de Clang requiere la compilación con la optimización del tiempo de vinculación (LTO). La LTO conserva la representación de código de bits de LLVM de los archivos de objeto hasta el tiempo de vinculación, lo que permite que el compilador razone mejor sobre qué optimizaciones se pueden realizar. En las pruebas realizadas en Android, la combinación de LTO y CFI generó una sobrecarga insignificante en el tamaño y el rendimiento del código. Sin embargo, habilitar LTO aumenta significativamente el tiempo de compilación del kernel.
Clang KCFI no requiere LTO, por lo que los kernels de Android más recientes se benefician de la CFI sin la sobrecarga de tiempo de compilación de LTO.
Implementación
La CFI se controla con la opción CONFIG_CFI_CLANG, que habilita la CFI de Clang o la KCFI de Clang.
Para obtener más detalles técnicos sobre el CFI y cómo se controlan otras verificaciones de control hacia adelante, consulta la documentación de diseño de LLVM. Allí, el KCFI se denomina -fsanitize=kcfi.
Solución de problemas
Después de habilitar la opción, soluciona cualquier error de discrepancia de tipos que pueda existir con sus controladores. Una llamada a función indirecta a través de un puntero de función incompatible activa la CFI. Cuando se detecta una falla de CFI, el kernel imprime una advertencia que incluye la función a la que se llamó y el registro de seguimiento que provocó la falla. Para corregir esto, asegúrate de que los punteros de función siempre tengan el mismo tipo que la función a la que se llama.
Para ayudar a depurar las fallas de CFI, habilita CONFIG_CFI_PERMISSIVE, que imprime una advertencia en lugar de provocar un error irrecuperable del kernel. El modo permisivo no se debe usar en producción.
Validación
Actualmente, no hay pruebas del CTS específicas para la CFI. En su lugar, asegúrate de que las pruebas del CTS se aprueben con la CFI habilitada y sin ella para verificar que la CFI no afecte el dispositivo.