safety critical - nist - ¿Qué idiomas se usan para el software de seguridad crítica?
nist pdf (17)
Estoy investigando el desarrollo de software crítico para la seguridad y, en particular, qué efectos tiene la elección del lenguaje de programación en dicho desarrollo.
Explique, en detalle, qué idiomas se usan comúnmente y por qué.
Apuntaría a Haskell si se trata de seguridad sobre todo lo demás. Propongo haskell porque tiene una comprobación de tipo estática muy rígida y promueve la programación en la que construyes piezas de manera que sean muy fáciles de probar.
Pero entonces no me importaría demasiado el lenguaje. Puede obtener una seguridad mucho mayor sin comprometer tanto al tener su proyecto en condiciones generales y trabajando sin plazos. En general, como tener toda la gestión básica del proyecto en su lugar. Tal vez me concentre en realizar pruebas exhaustivas para garantizar que todo funcione como debería, pruebas que cubren todos los casos de esquina y más.
Aquí hay algunas actualizaciones para algunas herramientas que no había visto aún y con las que he estado jugando últimamente que son bastante buenas.
La Infraestructura del compilador LLVM , una breve reseña en su página principal (incluye front-ends para C y C ++. Front-ends para Java, Scheme y otros lenguajes están en desarrollo);
Una infraestructura de compilación: LLVM también es una colección de código fuente que implementa el lenguaje y la estrategia de compilación. Los componentes principales de la infraestructura LLVM son un front-end C & C ++ basado en GCC, un marco de optimización de tiempo de enlace con un conjunto creciente de análisis y transformaciones globales e interprocedurales, back-ends estáticos para X86, X86-64, PowerPC Arquitecturas 32/64, ARM, Thumb, IA-64, Alpha, SPARC, MIPS y CellSPU, un back-end que emite código C portátil y un compilador Just-In-Time para X86, X86-64, PowerPC 32/64 procesadores y un emisor para MSIL.
VCC ;
VCC es una herramienta que demuestra la corrección de programas simultáneos anotados o encuentra problemas en ellos. VCC extiende C con características de diseño por contrato, como pre y poscondición, así como también tipos de invariantes. Los programas anotados se traducen a fórmulas lógicas utilizando la herramienta Boogie, que los pasa a un solucionador SMT automatizado Z3 para verificar su validez.
VCC utiliza la Infraestructura del compilador común recientemente lanzada.
Ambas herramientas, LLVM o VCC están diseñadas para admitir múltiples lenguajes y arquitecturas, creo que es un aumento en la codificación por contrato y otras prácticas formales de verificación.
WPF (no es el marco de MS :), es un buen lugar para comenzar si está tratando de evaluar algunas de las investigaciones y herramientas recientes en el espacio de validación del programa.
WG23 embargo, WG23 es el recurso principal para los detalles del lenguaje de desarrollo de sistemas críticos bastante actuales y específicos. Cubren todo, desde Ada, C, C ++, Java, C #, secuencias de comandos, etc. ... y tienen, como mínimo, un conjunto decente de referencia y orientación para orientar la actualización de información sobre vulnerabilidades y defectos específicos del lenguaje.
Como no das una plataforma, tendría que decir C / C ++. En la mayoría de las plataformas en tiempo real, de todos modos tiene opciones de acceso relativamente limitadas.
Los inconvenientes de la tendencia de C de permitirte disparar en el pie se compensa con la cantidad de herramientas para validar el código y la estabilidad y la asignación directa del código a las capacidades de hardware de la plataforma. Además, para cualquier aspecto crítico, no podrá confiar en software de terceros que no haya sido revisado exhaustivamente, esto incluye la mayoría de las bibliotecas, incluso muchas de las proporcionadas por proveedores de hardware.
Como todo será su responsabilidad, quiere un compilador estable, un comportamiento predecible y un mapeo cercano al hardware.
Creo que Ada todavía está en uso en algunos proyectos gubernamentales que son de seguridad y / o misión crítica. Nunca he usado el idioma, pero está en mi lista de "aprender", junto con Eiffel. Eiffel ofrece Design By Contract, que se supone que mejora la confiabilidad y la seguridad.
Cualquier producto de software puede pasar el proceso de certificación DO-178b utilizando cualquier herramienta, pero la pregunta es qué tan difícil sería. Si el compilador no está certificado, es posible que deba demostrar que su código es rastreable en el nivel de ensamblaje. Por lo tanto, es útil que su compilador esté certificado. Usamos C en nuestros proyectos, pero tuvimos que verificar en el nivel de ensamblaje y usar un estándar de código que incluía apagar el optimizador, uso limitado de la pila, uso de interrupciones limitadas, librerías transparentes certificables, etc. ADA no es polvo de duendes, sino que hace El plan de PSAC parece más alcanzable.
A medida que las aplicaciones crecen, el código de ensamblaje se convierte en una opción menos viable. El procesador ARM solo invita a C ++, pero si le preguntas a compañías como Kiel si su herramienta está certificada, volverán con un "¿eh?" Y no olvide que las herramientas de verificación también deben ser certificadas. Intente verificar un programa de prueba LabView.
El lenguaje y el sistema operativo es importante, pero también lo es el diseño. Trata de mantenerlo puro, simple.
Comenzaría teniendo el mínimo de información de estado (datos en tiempo de ejecución), para minimizar la posibilidad de que sea inconsistente. Luego, si desea tener redundancia para la tolerancia a fallas, asegúrese de tener formas infalibles para recuperarse de los datos que se vuelven inconsistentes. La redundancia sin una forma de recuperarse de la incoherencia es solo pedir problemas.
Siempre tenga una alternativa para cuando las acciones solicitadas no se completen en un tiempo razonable. Como dicen en el control del tráfico aéreo, una autorización no reconocida no es una autorización.
No tengas miedo de los métodos de votación. Son simples y confiables, incluso si pueden desperdiciar algunos ciclos. Evite el procesamiento que depende únicamente de eventos o notificaciones, ya que se puede descartar, duplicar o desordenar fácilmente. Como complemento de las encuestas, están bien.
Un amigo mío en el proyecto APOLLO comentó una vez que sabía que se estaban poniendo serios cuando decidieron confiar en las encuestas, en lugar de los eventos, a pesar de que la computadora era tremendamente lenta.
PD. Acabo de leer los estándares de C ++ Air Vehicle. Están bien, pero parecen suponer que habrá muchas clases, datos, punteros y asignación de memoria dinámica. Eso es exactamente lo que no debería ser más que absolutamente necesario. Debería haber un zar de estructura de datos con una gran guadaña.
El sistema operativo es más importante que el lenguaje. Use un núcleo en tiempo real como VxWorks o QNX. Miramos a ambos para controlar robots industriales y decidimos ir con VxWorks. Usamos C para el control real del robot.
Para un software realmente crítico, como los sistemas de autopromoción de aeronaves, quiere que múltiples procesadores se ejecuten de forma independiente para verificar los resultados.
En primer lugar, el software de seguridad crítica se adhiere a los mismos principios que se verían en los campos clásicos de la ingeniería mecánica y eléctrica. Redundancia, tolerancia a fallas y seguridad contra fallas.
Como un aparte, y como el cartel anterior aludió (y por alguna razón fue votado negativamente), el factor más importante para poder lograr esto es que su equipo tenga una sólida comprensión de todo lo que está sucediendo. No hace falta decir que un buen diseño de software de su parte es la clave. Pero también implica un lenguaje accesible, maduro, bien respaldado, para el cual hay mucho conocimiento común y desarrolladores experimentados disponibles.
Muchos carteles ya han comentado que el sistema operativo es un elemento clave en este sentido, que es muy cierto porque debe ser determinista (ver QNX o VxWorks). Esto descarta la mayoría de los lenguajes interpretados que hacen cosas detrás de escena para usted.
La ADA es una posibilidad, pero hay menos herramientas y apoyo, y lo que es más importante, las personas estelares no están tan disponibles.
C ++ es una posibilidad, pero solo si aplica estrictamente un subconjunto. En este sentido, es la herramienta del diablo, que promete hacernos la vida más fácil, pero que a menudo hace demasiado,
C es ideal. Es muy maduro, rápido, tiene un conjunto diverso de herramientas y soporte, muchos desarrolladores experimentados, multiplataforma y extremadamente flexibles, pueden trabajar cerca del hardware.
Me he desarrollado en todo, desde smalltalk hasta ruby, y aprecio y disfruto todo lo que los idiomas superiores tienen para ofrecer. Pero cuando estoy haciendo un desarrollo crítico de sistemas, muerdo la bala y me quedo con C. En mi experiencia (defensa y muchos dispositivos médicos de clase II y III), menos es más.
HAL / S se usa para el transbordador espacial.
Hay muchas buenas referencias en http://www.dwheeler.com ("software de alta seguridad").
Para cosas automotrices, vea el estándar MISRA C. C, pero no puedes usar más de dos niveles de punteros y otras cosas así.
adahome.com tiene buena información sobre Ada. Me gustó este tutorial de C ++ a Ada: http://adahome.com/Ammo/cpp2ada.html
Para hard-time, Tom Hawkins ha hecho algunas cosas interesantes de Haskell. Ver: ImProve (el lenguaje incorpora un solucionador de SMT para verificar las condiciones de verificación) y Atom (EDSL para la programación simultánea en tiempo real sin usar hilos o tareas reales).
Java es un lenguaje nocturno por muchas razones. Fue diseñado por un idiota que malinterpretó los proyectos Pascal y Oberon del Prof. Wirth.
ADA fue un lenguaje diseñado por un comité grande, y la expansión resultante me recuerda mucho a PL / 1, que fue maravilloso, pero tan complicado de escribir un compilador que nadie lo recogió.
Modula-2 es probablemente el lenguaje más simple que se haya diseñado, y en lugar de C, he usado modula-2 con un tamaño de código de la mitad de las líneas (y por lo tanto, funciona el doble de rápido). C está solo un paso por encima del ensamblador, y solo por respirar demasiado fuerte puedes crear un error desagradable.
Pascal y básico son lenguajes muy confiables. De hecho, el compilador / kit de herramientas de Visual Basic 6 es probablemente lo mejor que MS haya producido, y la gente todavía lo usa 15 años después de que fue abandonado por MS. No me hagas comenzar con la abominación que es .NET, la pila de mierda más espantosamente complicada que ha salido de MS, que quería crear un sistema patentado que nadie podría clonar nunca. Lástima que nadie quiere clonarlo! ellos tienen demasiado éxito en hacer algo oscuro.
Eiffel es intrínsecamente confiable, ya que utiliza pequeños subprocesos con sus propios montones y montones que se recopilan cuando finaliza la subtarea, por lo que no se fragmenta la memoria. Pero buena suerte para entender a Eiffel, fue obra de un loco. Lo mismo vale para Miranda, y muchos de los lenguajes académicos que fueron diseñados por fanáticos de las matemáticas en lugar de personas que están acostumbradas a lograr algo práctico.
Diría que Python es uno de los mejores idiomas. Fácil de leer, rápido y simple. No es particularmente seguro, pero para guiones, supera los pantalones de los guiones de shell Bash, o el cielo no lo permita, el lenguaje atroz de solo escritura llamado Perl.
Los entornos en tiempo real generalmente tienen requisitos de "seguridad crítica". Para ese tipo de cosas, podría mirar VxWorks , un popular sistema operativo en tiempo real. Actualmente está en uso en muchos ámbitos diversos, como aviones Boeing, interiores BMW iDrive, controladores RAID y diversas naves espaciales. ( Compruébalo )
El desarrollo de la plataforma VxWorks se puede realizar con varias herramientas, entre ellas Eclipse , Workbench , SCORE y otras. C, C ++, Ada y Fortran (sí, Fortran) son compatibles, así como algunos otros.
No sé qué idioma utilizaría, pero sí sé qué idioma no usaría:
NOTA SOBRE APOYO JAVA. EL PRODUCTO DE SOFTWARE PUEDE CONTENER SOPORTE PARA PROGRAMAS ESCRITOS EN JAVA. JAVA TECHNOLOGY NO ES TOLERANTE A FALLOS Y NO ESTÁ DISEÑADO, FABRICA O ESTÁ DISEÑADO PARA SER USADO O REVENDIDO COMO EQUIPO DE CONTROL EN LÍNEA EN ENTORNOS PELIGROSOS QUE REQUIEREN RENDIMIENTO SEGURO DE FALLOS, COMO EN EL FUNCIONAMIENTO DE INSTALACIONES NUCLEARES, NAVEGACIÓN DE AERONAVES O SISTEMAS DE COMUNICACIÓN, AIRE MÁQUINAS DE CONTROL DE TRAFICO, MÁQUINAS DE APOYO DIRECTO O SISTEMAS DE ARMAS, EN LAS CUALES LA FALLA DE LA TECNOLOGÍA DE JAVA PODRÍA CAUSAR DIRECTAMENTE LA MUERTE, LESIONES PERSONALES O DAÑOS FÍSICOS O AMBIENTALES GRAVES.
Para C ++, el Estándar de Codificación C ++ Joint Strike Fighter (F-35) es una buena lectura:
Un lenguaje que impone patrones cuidadosos puede ayudar, pero puede imponer patrones cuidadosos utilizando cualquier lenguaje, incluso ensamblador. Cada suposición sobre cada valor necesita un código que pruebe la suposición. Por ejemplo, siempre prueba el divisor para cero antes de dividir.
Cuanto más pueda confiar en los componentes reutilizables, más fácil será la tarea, pero los componentes reutilizables rara vez se certifican para un uso crítico y no lo guiarán a través de los procesos de seguridad regulatorios. Debería usar un pequeño kernel de sistema operativo y luego construir pequeños módulos que sean probados en unidades con entrada aleatoria. Un lenguaje como Eiffel podría ayudar, pero no hay una bala de plata.
Un nuevo estándar de seguridad crítica para Java se encuentra actualmente en desarrollo: JSR 302: Tecnología Java de Seguridad Crítica .
La Java de Seguridad Crítica (SCJ) se basa en un subconjunto de RTSJ. El objetivo es contar con un marco adecuado para el desarrollo y análisis de programas de seguridad crítica para la certificación de seguridad crítica (DO-178B, Nivel A y otros estándares de seguridad crítica).
SCJ, por ejemplo, elimina el montón, que aún está presente en RTSJ, también define 3 niveles de cumplimiento a los que pueden ajustarse tanto la aplicación como la VM, los niveles de cumplimiento se definen para facilitar la certificación de aplicaciones complejas.
Recursos :
Ada y SPARK (que es un dialecto de Ada con algunos ganchos para verificación estática) se utilizan en los círculos aeroespaciales para la construcción de software de alta fiabilidad, como los sistemas de aviónica. Existe algo así como un ecosistema de herramientas de verificación de códigos para estos lenguajes , aunque esta tecnología también existe para más idiomas convencionales .
Erlang fue diseñado desde cero para escribir código de telecomunicaciones de alta confiabilidad . Está diseñado para facilitar la separación de las preocupaciones por la recuperación de errores (es decir, el subsistema que genera el error es diferente del subsistema que maneja el error). También puede estar sujeto a pruebas formales, aunque esta capacidad no se ha alejado mucho de los círculos de investigación.
Los lenguajes funcionales como Haskell pueden estar sujetos a pruebas formales por parte de sistemas automatizados debido a la naturaleza declarativa del lenguaje. Esto permite que el código con efectos secundarios esté contenido en funciones monádicas. Para una prueba de corrección formal, se puede suponer que el resto del código no hace más que lo que se especifica.
Sin embargo, estos lenguajes son basura recolectada y la recolección de basura es transparente para el código, por lo que no se puede razonar de esta manera. Los lenguajes recolectados de basura normalmente no son lo suficientemente predecibles para aplicaciones duras en tiempo real, aunque existe un cuerpo de investigación continua en recolectores de basura incrementales de tiempo limitado.
Eiffel y sus descendientes tienen soporte integrado para una técnica llamada Design By Contract que proporciona un mecanismo robusto de tiempo de ejecución para incorporar controles previos y posteriores para invariants. Aunque Eiffel nunca llegó a entenderse, desarrollar software de alta confiabilidad tiende a consistir en escribir cheques y manejadores para los modos de falla por adelantado antes de escribir la funcionalidad.
Aunque C y C++ no se diseñaron específicamente para este tipo de aplicaciones, son ampliamente utilizados para software incrustado y crítico para la seguridad por varias razones. Las principales propiedades de la nota son el control sobre la administración de la memoria (que le permite evitar la recolección de elementos no utilizados, por ejemplo), las bibliotecas centrales sencillas y bien depuradas y el soporte maduro de herramientas. Muchas de las cadenas de herramientas de desarrollo integradas actualmente en uso se desarrollaron por primera vez en las décadas de 1980 y 1990 cuando esta era la tecnología actual y provenían de la cultura Unix que prevalecía en ese momento, por lo que estas herramientas siguen siendo populares para este tipo de trabajo.
Si bien el código de administración de memoria manual se debe verificar cuidadosamente para evitar errores, permite un grado de control sobre los tiempos de respuesta de la aplicación que no está disponible con los idiomas que dependen de la recolección de basura. Las bibliotecas de tiempo de ejecución central de los lenguajes C y C ++ son relativamente simples, maduras y bien entendidas, por lo que se encuentran entre las plataformas más estables disponibles. La mayoría, si no todas, las herramientas de análisis estático utilizadas para Ada también admiten C y C ++, y hay muchas otras herramientas disponibles para C. También hay several chains tool based C/C++ widely used ; la mayoría de las cadenas de herramientas utilizadas para Ada también vienen en versiones que admiten C y / o C ++.
Los métodos formales como Semántica Axiomática (PDF), Notación Z o Procesos secuenciales de comunicación permiten que la lógica del programa sea matemáticamente verificada, y se utilizan a menudo en el diseño de software de seguridad crítica donde la aplicación es lo suficientemente simple para aplicarlos (típicamente sistemas de control integrados) . Por ejemplo, uno de mis ex conferenciantes hizo una prueba formal de corrección de un sistema de señalización para la red ferroviaria alemana.
La principal deficiencia de los métodos formales es su tendencia a crecer exponencialmente en complejidad con respecto al sistema subyacente que se está probando. Esto significa que existe un riesgo significativo de errores en la prueba, por lo que están prácticamente limitados a aplicaciones bastante simples. Los métodos formales se utilizan ampliamente para verificar la corrección del hardware, ya que los errores de hardware son muy costosos de solucionar, especialmente en los productos del mercado masivo. Desde el error Pentium FDIV , los métodos formales han ganado bastante atención, y se han utilizado para verificar la corrección de la FPU en todos los procesadores Intel desde el Pentium Pro.
Muchos otros idiomas se han utilizado para desarrollar software altamente confiable. Se han realizado muchas investigaciones sobre el tema. Se puede argumentar razonablemente que la metodología es más importante que la plataforma, aunque existen principios como la simplicidad, la selección y el control de las dependencias que pueden impedir el uso de ciertas plataformas .
Como han señalado varios de los otros, ciertas plataformas de O / S tienen características para promover la confiabilidad y el comportamiento predecible, como los temporizadores de vigilancia y los tiempos de respuesta de interrupción garantizados. La simplicidad también es un fuerte impulsor de la confiabilidad, y muchos sistemas RT se mantienen deliberadamente de forma muy simple y compacta. QNX (el único O / S con el que estoy familiarizado, habiendo trabajado una vez con un sistema de dosificación de concreto basado en él) es muy pequeño y cabe en un disquete único. Por razones similares, las personas que hacen que OpenBSD , que es conocido por su seguridad robusta y auditoría exhaustiva de código, también se desviven por mantener el sistema simple.
EDITAR: Esta publicación contiene algunos enlaces a buenos artículos sobre software crítico para la seguridad, en particular Here y Here . Apoyos a S.Lott y Adam Davis para la fuente. La historia del THERAC-25 es un poco un trabajo clásico en este campo.