¿Cuáles son las posibles dificultades al tener un núcleo mínimo que ejecuta código administrado?
14
Supongamos que quiero construir un sistema operativo basado en un kernel inferior nativo muy pequeño que actúe como un intérprete de código administrado / tiempo de ejecución y un kernel superior más grande compilado en un lenguaje de máquina no nativo (código de bytes Java, CIL, etc.). Ejemplos de sistemas operativos similares serían Singularity y Cosmos .
¿Qué dificultades y desafíos de desarrollo existen al escribir un sistema operativo con este tipo de infraestructura en contraste con una solución puramente nativa?
Dependiendo del idioma, puede haber muchos desafíos de desarrollo:
Punteros: si un idioma no tiene punteros, será un desafío realizar tareas relativamente fáciles. Por ejemplo, puede usar punteros para escribir en la memoria VGA para imprimir en la pantalla. Sin embargo, en un lenguaje administrado, necesitará algún tipo de "plug" (de C / C ++) para hacer lo mismo.
Ensamblaje: un sistema operativo siempre necesita un ensamblaje. Lenguajes como C #, Java, etc. no funcionan tan bien con él, a diferencia de C / C ++. En C o C ++ también puede tener un ensamblaje en línea que es muy, muy útil para muchas tareas. Hay MUCHOS casos en los que esto es necesario (ejemplos en x86): cargar un GDT, cargar un IDT, habilitar la paginación, configurar IRQ, etc.
Control: si estás usando algo como Cosmos, no tienes control total. Cosmos es un micro-núcleo y esencialmente "arranca" su "núcleo". Puede implementar algo como Cosmos desde cero si realmente quisiera, sin embargo, eso puede llevar mucho, mucho tiempo.
Gastos generales: con los lenguajes administrados, hay MUCHO gasto indirecto en comparación con C o incluso C ++. Cosas como Cosmos necesitan implementar muchas cosas antes de que incluso se pueda ejecutar un kernel C # hello world. En C, está listo para comenzar, no se necesita una configuración real. En C ++, solo hay algunas cosas que deben implementarse para usar algunas de las funciones de C ++.
Estructuras: en C / C ++ hay estructuras que muchos lenguajes administrados no tienen, por lo que necesitaría implementar alguna forma de tener algo como una estructura. Por ejemplo, si desea cargar una IDT (tabla de descriptores de interrupción), en C / C ++, puede crear una estructura (con un atributo empaquetado) y cargarla utilizando el lidt de instrucciones x86 ASM . En un lenguaje administrado, esto es mucho más difícil de hacer ...
Los lenguajes administrados, en cuanto a sintaxis, son más fáciles, sin embargo, para muchas cosas relacionadas con el sistema operativo muchas veces no son muy adecuadas. Eso no significa que no se puedan usar, sin embargo, a menudo se recomienda algo como C / C ++.
Esta respuesta es bastante débil. ¿Cuáles son las "tareas relativamente fáciles" que no puedes hacer sin punteros (excluyendo una base pequeña)? ¿Cuáles son las partes que necesitan ensamblaje? ¿Qué control te falta? ¿En qué basa su declaración sobre los gastos generales? ¿Por qué no puedes tener estructuras en un lenguaje administrado?
Gilles 'SO- deja de ser malvado'
1. No hay ninguna razón por la cual un lenguaje administrado no ofrezca la capacidad de acceder a la memoria VGA, es solo el mapeo / desasignación que debería proporcionarse como una primitiva (una primitiva de administración de memoria). 2. Algunas tareas de cambio (p. Ej., Guardar registros) generalmente deben realizarse como código ensamblador, pero está muy localizado, no es un argumento en contra de tener el 99% del sistema operativo en un idioma administrado. Manipular la MMU es una primitiva de gestión de memoria. 4. C también necesita configuración (configurar una pila y un montón); Los lenguajes administrados necesitan un poco más de configuración, pero no hay una diferencia cualitativa.
Gilles 'SO- deja de ser malvado'
@Gilles, la pregunta es cuáles son los desafíos de desarrollo para usar un lenguaje administrado. Estos son desafíos de desarrollo, sin embargo, aún puede superarlos con éxito ...
El problema es que los tipos de errores que pueden causar un agujero de seguridad son muy diferentes de lo que los investigadores de seguridad están acostumbrados. En un microkernel tradicional, todos los controladores y otras subpartes del núcleo están aislados entre sí ejecutándolos en diferentes espacios de direcciones. En un microkernel donde el aislamiento se implementa a través del código administrado de verificación de tipo, se evitan los enormes gastos generales de cambiar los espacios de direcciones cada vez que se necesita usar un subservicio, pero la desventaja es que ahora evaluar el mecanismo de aislamiento es más difícil.
Cualquier parte particular del kernel (digamos un controlador de dispositivo) escrita en el lenguaje administrado es segura si y solo si el verificador de tipo dice que el controlador es seguro y el verificador de tipo no tiene errores. Entonces el verificador de tipo es parte del núcleo del núcleo. En la práctica, parece que los verificadores de tipo son considerablemente más grandes y más complicados que los núcleos de microkernel tradicionales. Eso significa que la superficie de ataque es potencialmente más grande.
No sé si las técnicas tradicionales de aislamiento de micro-kernel o las técnicas de aislamiento basadas en código administrado son realmente más o menos confiables. Aquí hay un problema de arranque: hasta que las técnicas de aislamiento de código administrado sean ampliamente utilizadas, no sabremos con qué frecuencia son inseguras. Pero sin saber cuán inseguros son, es difícil implementarlos en situaciones que son críticas para la seguridad.
Encuentro estos argumentos muy extraños. (De acuerdo, mi experiencia puede estar sesgada por los métodos formales, pero esta no es la única base para mi opinión). Un typechecker no es tan complejo, en comparación con un microkernel más un MMU. Por ejemplo, el microkernel de Coq tiene aproximadamente 14kLoC de OCaml, más grande que un microkernel, pero no mucho, y está escrito en un lenguaje que es menos propenso a errores que la mayoría de los núcleos (sin C ni ensamblador). Los verificadores de tipo no son susceptibles a las condiciones de carrera, que son una clase de errores particularmente sutil.
Gilles 'SO- deja de ser malvado'
El código administrado brinda una mejor oportunidad para manejar cierta clase de errores; por ejemplo, el análisis del flujo de información puede probar la ausencia de canales laterales (es probable que tome mucho trabajo, y no sé en qué medida se ha hecho, pero es factible en principio), mientras que el aislamiento de hardware solo le permite probar los canales laterales en los que has pensado.
Gilles 'SO- deja de ser malvado'
En el aspecto práctico, varias máquinas virtuales que proporcionan aislamiento han sido certificadas en EAL5 y superiores. Aquí hay dos ejemplos que puede tener en su billetera si es europeo, porque se usan en tarjetas inteligentes como tarjetas de crédito: MULTOS , plataforma abierta Java Card . En la comunidad de evaluación de seguridad, he escuchado muchas dudas de que el aislamiento de MMU podría ir más allá de EAL2.
He oído decir (por un investigador que trabaja en una técnica de microkernel competitiva ) que se sabe muy poco acerca de cómo evaluar la seguridad de los sistemas que son extensibles a través del código administrado.
El problema es que los tipos de errores que pueden causar un agujero de seguridad son muy diferentes de lo que los investigadores de seguridad están acostumbrados. En un microkernel tradicional, todos los controladores y otras subpartes del núcleo están aislados entre sí ejecutándolos en diferentes espacios de direcciones. En un microkernel donde el aislamiento se implementa a través del código administrado de verificación de tipo, se evitan los enormes gastos generales de cambiar los espacios de direcciones cada vez que se necesita usar un subservicio, pero la desventaja es que ahora evaluar el mecanismo de aislamiento es más difícil.
Cualquier parte particular del kernel (digamos un controlador de dispositivo) escrita en el lenguaje administrado es segura si y solo si el verificador de tipo dice que el controlador es seguro y el verificador de tipo no tiene errores. Entonces el verificador de tipo es parte del núcleo del núcleo. En la práctica, parece que los verificadores de tipo son considerablemente más grandes y más complicados que los núcleos de microkernel tradicionales. Eso significa que la superficie de ataque es potencialmente más grande.
No sé si las técnicas tradicionales de aislamiento de micro-kernel o las técnicas de aislamiento basadas en código administrado son realmente más o menos confiables. Aquí hay un problema de arranque: hasta que las técnicas de aislamiento de código administrado sean ampliamente utilizadas, no sabremos con qué frecuencia son inseguras. Pero sin saber cuán inseguros son, es difícil implementarlos en situaciones que son críticas para la seguridad.
fuente