Seguridad del kernel de Linux bien hecha


Para pedir prestado a un excelente analogía Entre el ecosistema informático moderno y la industria automotriz estadounidense de la década de 1960, el kernel de Linux funciona bien: cuando conduce por la carretera, no se le rocía la cara con aceite y gasolina, y rápidamente llega a donde quiere ir. Sin embargo, ante la falla, el automóvil puede terminar en llamas y volar por un acantilado.

A medida que nos acercamos a su 30 aniversario, Linux sigue siendo el proyecto de desarrollo colaborativo más grande en la historia de la informática. La enorme comunidad que rodea a Linux le permite hacer cosas increíbles y funcionar sin problemas. Sin embargo, lo que todavía falta es suficiente enfoque para asegurarse de que Linux falla bien también. Existe un fuerte vínculo entre la robustez del código y la seguridad: hacer que sea más difícil que se manifiesten los errores hace que sea más difícil que se manifiesten las fallas de seguridad. Pero ese no es el last de la historia. Cuando las fallas se manifiestan, es importante manejarlas de manera efectiva.

En lugar de tomar una perspectiva de un mistake a la vez, las acciones preventivas pueden evitar que los errores tengan efectos negativos. Con Linux escrito en C, seguirá teniendo una larga cola de asociados problemas. Linux debe estar diseñado para tomar medidas proactivas para defenderse de sus propios riesgos. Los autos tienen cinturones de seguridad no porque queramos chocar, sino porque está garantizado que sucederá a veces.

A pesar de que todos quieren un kernel seguro que se ejecute en su computadora, teléfono, automóvil o helicóptero interplanetario, no todo el mundo está en condiciones de hacer algo al respecto. Los desarrolladores de kernel ascendentes pueden corregir errores, pero no tienen handle sobre lo que un proveedor descendente elige incorporar a sus productos. Los usuarios finales pueden elegir sus productos, pero generalmente no tienen command sobre qué errores se corrigen ni qué kernel se usa (un problema en si mismo). En última instancia, los proveedores son responsables de mantener seguros los núcleos de sus productos.

¿Qué arreglar?

Las estadísticas de seguimiento y corrección de distintos errores son aleccionadoras. El lanzamientos de kernel estables («solo correcciones de errores») cada una contiene cerca de 100 correcciones nuevas por semana. Frente a esta alta tasa de cambio, un proveedor puede optar por ignorar todas las correcciones, elegir solo las correcciones «importantes» o enfrentarse a la abrumadora tarea de tomar todo.

¿No arreglar nada?

Con preponderancia de malware, botnets y vigilancia estatal apuntar a computer software defectuoso, está claro que ignorar todas las correcciones es la «solución» incorrecta. Desafortunadamente, esta es la postura muy común de los proveedores que ven sus dispositivos como solo un producto físico en lugar de un producto / servicio híbrido que debe ser regularmente actualizado.

¿Arreglar fallas importantes?

Entre la negligencia de no hacer nada y la carga asumida de arreglar todo, la elección tradicional del proveedor ha sido seleccionar solo las correcciones «importantes». Pero, ¿qué constituye «importante» o incluso relevante? Solo determinando si implementar una corrección requiere tiempo para el desarrollador.

La sabiduría predominante ha sido elegir las vulnerabilidades para corregir en función de Mitre CVE checklist, asumiendo que todas las fallas importantes (y por lo tanto las correcciones) tendrían un CVE asociado. Sin embargo, dado el volumen de fallas y su aplicabilidad a un sistema en unique, no todas las fallas de seguridad tienen CVE asignados, ni se asignan de manera oportuna. La evidencia muestra que para los CVE de Linux, más del 40% se había corregido antes incluso de que se asignara el CVE, siendo el retraso promedio más de tres meses después de la corrección. Algunas correcciones pasaron años sin que se reconozca su impacto en la seguridad. Además de esto, los errores relevantes para el producto pueden ni siquiera clasificar para un CVE. Por último, los desarrolladores ascendentes no están realmente interesados ​​en Asignación de CVE pasan su tiempo limitado realmente corrigiendo errores.

Un proveedor que confía en la selección selectiva tiene casi la garantía de pasar por alto vulnerabilidades importantes que otros están solucionando activamente, lo que es casi peor que no hacer nada, ya que crea la ilusión de que las actualizaciones de seguridad se están manejando de manera adecuada.

¡Arregla todo!

Entonces, ¿qué debe hacer un proveedor? La respuesta es easy, aunque dolorosa: actualice continuamente a la última versión del kernel, ya sea mayor o estable. Hacer un seguimiento de los lanzamientos importantes significa ganar mejoras de seguridad junto con correcciones de errores, mientras que las versiones estables son solo correcciones de errores. Por ejemplo, aunque los teléfonos Android modernos se envían con kernels que se basan en versiones principales de casi dos o cuatro años antes, Los proveedores de Android ahora, afortunadamente, rastrear lanzamientos de kernel estables. Por lo tanto, aunque faltarán las funciones que se están agregando a los kernels principales más nuevos, están presentes todas las últimas correcciones estables del kernel.

La realización de actualizaciones continuas del kernel (importantes o estables), comprensiblemente, enfrenta una enorme resistencia dentro de una organización debido al temor a las regresiones. ¿La actualización romperá el producto? La respuesta suele ser que un proveedor no lo sabe o que la frecuencia de actualización es más corta que el tiempo necesario para realizar las pruebas. Pero el problema con la actualización no es que el kernel pueda causar regresiones es que los proveedores no tienen suficiente cobertura de pruebas y automatización para conocer la respuesta. Las pruebas deben tener prioridad sobre las correcciones individuales.

Haz que suceda

Queda una pregunta: ¿cómo soportar todo el trabajo que requieren las actualizaciones continuas? Resulta que es un straightforward problema de asignación de recursos y se logra más fácilmente de lo que se podría imaginar: la redundancia descendente se puede mover hacia una mayor colaboración ascendente.

Más ingenieros para corregir errores antes

Con los proveedores que utilizan kernels antiguos y respaldan las correcciones existentes, sus recursos de ingeniería están haciendo un trabajo redundante. Por ejemplo, en lugar de que 10 empresas asignen cada una un ingeniero para respaldar la misma solución de forma independiente, esas horas de desarrollador podrían trasladarse al trabajo ascendente, donde se podrían corregir 10 errores separados para todos en el ecosistema de Linux. Esto ayudaría a abordar la creciente acumulación de errores. Al observar solo una fuente de posibles fallas de seguridad del kernel, tablero de syzkaller muestra que el número de errores abiertos se acerca actualmente a 900 y crece aproximadamente 100 al año, incluso con aproximadamente 400 al año siendo arreglado.

Más ingenieros para la revisión de código

Más allá de simplemente eliminar los errores después del hecho, un mayor enfoque en la revisión del código anterior ayudará a detener la marea de su introducción en primer lugar, con beneficios que se extienden más allá de los errores detectados inmediatamente. Código capaz revisar el ancho de banda es un recurso limitado. Sin suficiente gente dedicada Para tareas de mantenimiento de subsistemas y revisión de código en sentido ascendente, todo el proceso de desarrollo del kernel se atasca.

La solidez de Linux a largo plazo depende de los desarrolladores, pero especialmente de un kernel eficaz mantenedores. Aunque hay un esfuerzo en la industria para tren nuevos desarrolladores, esto se ha justificado tradicionalmente solo por los trabajos «basados ​​en funciones» que pueden obtener. Pero centrarse solo en las líneas de tiempo de los productos lleva a Linux a la Tragedia de los comunes. Ampliar el número de mantenedores puede evitarlo. Afortunadamente, la «tubería» para los nuevos mantenedores es sencilla.

Los mantenedores se crean no solo a partir de su profundo conocimiento de la tecnología de un subsistema, sino también de su experiencia con la tutoría de otros desarrolladores y la revisión de código. La formación de nuevos revisores debe convertirse en la norma, motivados por hacer que la revisión previa sea parte del trabajo. Los revisores de hoy se convierten en los mantenedores del mañana. Si cada subsistema principal del kernel ganara cuatro mantenedores más dedicados, podríamos doble productividad.

Más ingenieros para pruebas e infraestructura

Junto con más revisores, la mejora de Linux flujo de trabajo de desarrollo es elementary para ampliar la capacidad de contribución de todos. El flujo de trabajo de «solo correo electrónico» de Linux es mostrando su edad, pero el desarrollo ascendente de más automatizado seguimiento de parches, integración continua, fuzzing, cobertura, y pruebas hará que el proceso de desarrollo sea significativamente más eficiente.

Además, en lugar de probar los núcleos después de su lanzamiento, es más efectivo probarlos durante el desarrollo. Cuando se realizan pruebas con versiones de kernel no publicadas (p. Ej. linux-siguiente) y reportado aguas arriba, los desarrolladores obtienen comentarios inmediatos sobre los errores. Las correcciones se pueden desarrollar antes de que se publique una falla siempre es más fácil corregir un error más temprano que tarde.

Esta «río arriba primero«El enfoque para el desarrollo y las pruebas del kernel del producto es extremadamente eficaz. Google lo ha estado haciendo con éxito con Sistema operativo Chrome y Androide desde hace un tiempo, y no está solo en la industria. Significa que el desarrollo de características ocurre en el último kernel, y los dispositivos se prueban de manera very similar lo más cerca posible de los últimos kernels ascendentes, evitando todo esfuerzo duplicado «interno».

Más ingenieros para el desarrollo de cadenas de herramientas y seguridad

Además de tratar de manera reactiva los errores individuales y las necesidades de mantenimiento existentes, también existe la necesidad de eliminar de forma proactiva clases enteras de defectos, de modo que los desarrolladores no puedan volver a introducir este tipo de errores nunca más. ¿Por qué corregir el mismo tipo de vulnerabilidad de seguridad 10 veces al año cuando podemos evitar que vuelva a aparecer?

En los últimos años, se han eliminado o reemplazado varias funciones de lenguaje frágiles y API del kernel (p. Ej. VLA, interruptor de caída, addr_limit). Sin embargo, todavía hay mucho más trabajo por hacer. Uno de los aspectos que más tiempo ha consumido ha sido la refactorización involucrada en hacer estos cambios usualmente invasivos y sensibles al contexto en los 25 millones de líneas de código de Linux.

Más allá del código del kernel en sí, el compilador y la cadena de herramientas también necesitan desarrollar funciones más defensivas (p. Ej. puesta a cero variable, CFI, desinfectantes). Con la cadena de herramientas técnicamente «fuera» del kernel, su esfuerzo de desarrollo a menudo se pasa por alto de manera inapropiada y se invierte insuficientemente. Las cargas de seguridad del código deben trasladarse tanto como sea posible a la cadena de herramientas, liberando a los humanos para trabajar en otras áreas. En el frente más progresivo, debemos asegurarnos de que Linux se pueda escribir en lenguajes seguros para la memoria como Óxido.

No espere otro minuto

Si no está utilizando el kernel más reciente, no tiene las defensas de seguridad agregadas más recientemente (incluidas las correcciones de errores). Frente a las fallas recién descubiertas, esto deja a los sistemas menos seguros de lo que podrían haber sido. Incluso cuando está mediado por un diseño cuidadoso del sistema, un modelado de amenazas adecuado y otras prácticas de seguridad estándar, la magnitud del riesgo crece rápidamente con el tiempo, lo que deja a los proveedores hacer el cálculo para determinar la antigüedad del kernel al que pueden tolerar exponer a los usuarios. A menos que la respuesta sea «simplemente abandonar a nuestros usuarios», los recursos de ingeniería deben centrarse en la fase inicial para cerrar la brecha mediante la implementación continua de la última versión del kernel.

Con foundation en nuestras estimaciones más conservadoras, el kernel de Linux y sus cadenas de herramientas están actualmente subinvertidas por al menos 100 ingenieros, por lo que depende de todos reunir su talento de desarrollador en la etapa inicial. Esta es la única solución que garantizará un equilibrio de seguridad a un costo razonable a largo plazo.



Enlace a la noticia original