¿Qué impide que un programa de ensamblaje bloquee el sistema operativo? [cerrado]

18

En primer lugar, soy un principiante, por lo que si esta pregunta suena tonta, por favor señale los supuestos incorrectos.

Por lo que entiendo, el trabajo de un sistema operativo es administrar el hardware y el software que se ejecuta en el sistema operativo. Además, por lo que entiendo, los programas de ensamblaje permiten controlar el hardware casi directamente. En un programa de ensamblaje, uno puede leer y escribir datos en registros, y leer y escribir datos en RAM.

Dada esta libertad de meterse con los registros y la RAM, ¿no sería posible que los programas de ensamblaje afecten el sistema operativo? Suponga que un sistema operativo está utilizando el registro A para almacenar información crucial, y suponga que ejecuto un programa ensamblado en ese sistema operativo. Si el programa escribe correctamente la basura en el registro A, el sistema operativo seguramente se verá afectado.

Preguntas:

  1. ¿Es posible meterse con el registro A de la manera descrita anteriormente?

  2. Si no, ¿qué impide que los programas de ensamblaje modifiquen los registros utilizados por el sistema operativo?

Flujo
fuente
13
programadores inteligentes ...
Tony Stewart Sunnyskyguy EE75
Hay muchas arquitecturas de computadoras ahora y en el pasado, así como también se desarrollaron muchos sistemas operativos. ¿A qué arquitectura / sistema operativo se refiere exactamente? En algunas arquitecturas (antiguas) no había posibilidad de detener el programa de lo que estaba haciendo después del inicio, eso es correcto. Pero el hardware / SO moderno ha incorporado herramientas de hardware que proporcionan solo la parte de la memoria para el programa en modo "normal" (no superusuario), y no puede acceder a la memoria fuera de este límite. Los registros son de uso gratuito, ya que el sistema operativo no almacena ninguna información útil en los registros, solo en la memoria / en el disco.
ciclón125
2
En un microprocesador, su programa se ejecuta en "modo de usuario", los sistemas operativos se ejecutan en "modo de sistema". Si un programa en modo de usuario ejecutara una instrucción de detención, por ejemplo, la máquina no se detendría. El alto quedaría atrapado y el sistema operativo invocado. Con respecto a la RAM, el sistema operativo configuraría un entorno para el programa de modo de usuario de modo que, a través del hardware de administración de memoria, lo que el programa de usuario ve como la dirección de RAM X realmente no sería la dirección de RAM X.
George White
1
@flux He actualizado mi comentario. La respuesta sería: no hay una respuesta "general" a su pregunta, ya que hay / hubo diferentes arquitecturas de computadoras / SO. Puede ser de diferentes maneras.
ciclón125
2
... Hace mucho tiempo solía escribir en código máquina sin procesar. Yee ha !!! :-)
Russell McMahon

Respuestas:

33

Al final, todos los programas son código de máquina, independientemente de si el idioma de origen era ensamblador o un lenguaje de alto nivel.

Lo importante es que existen mecanismos de hardware que limitan lo que puede hacer un proceso determinado, incluidos los registros de "jugar con" que podrían afectar a otros programas o al propio sistema operativo.

Esto comenzó con una simple distinción entre los modos de operación "usuario" y "supervisor", y desde entonces se ha convertido en una arquitectura de seguridad con múltiples "anillos" de privilegios.


Aquí hay un ejemplo muy genérico para hacerlo un poco más concreto:

  • En "modo de usuario", un proceso no puede acceder a la memoria que no ha sido asignada a su ID de proceso. La memoria asignada a otros procesos y el propio sistema operativo está bloqueado. Esto incluye los valores de los registros utilizados por esos otros procesos. Esto es impuesto por el hardware MMU.

  • Por lo tanto, en "modo de usuario", un proceso no puede acceder a los registros de control de MMU.

  • Y, obviamente, en "modo de usuario", un proceso no puede cambiar el modo a "modo de supervisor", excepto a través de un mecanismo muy bien definido que implica llamar a una función del sistema operativo.

El sistema operativo obtiene el control si el proceso intenta romper alguna de estas reglas. Una vez que eso sucede, el sistema operativo simplemente puede detener el proceso ofensivo, sin ejecutar más instrucciones.

Dave Tweed
fuente
2
Si entiendo correctamente, lo que está diciendo es: algunos procesadores tienen "modo de usuario" y "modo de supervisor". El sistema operativo se ejecuta en "modo supervisor" y pone el procesador en "modo de usuario" para ejecutar mi programa de ensamblaje ficticio. En el "modo de usuario", hay registros y direcciones RAM a las que el programa de ensamblaje no puede acceder debido al diseño deliberado del hardware.
Flux
3
Básicamente, esta respuesta describe arquitecturas modernas "similares a i386" con MMU y modo protegido. Pero para ser verdad, hay muchas arquitecturas antiguas (i8080, MOS 6502, etc.) y modernas más simples (AVR, ARM Cortex-M, etc.) que no tienen estas características y si se utiliza algún tipo de sistema operativo (por ejemplo, antiguo CP / M, FreeRTOS moderno, ChibiOS, etc.) nada puede detener el programa de lo que está haciendo.
ciclón 125 el
2
@Flux Las arquitecturas i386 (y superiores) proporcionan detalles para aprender. La arquitectura x86 no solo tiene direcciones de memoria que se pueden proteger, sino también direcciones de E / S. (Existen diferentes instrucciones para el acceso a la memoria frente al acceso de E / S). Hay tres direcciones de memoria en el i386 +. La dirección segmentada / basada en el selector utiliza un registro selector que hace referencia a una entrada de tabla (GDT o LDT) para asignar el par en una sola dirección lineal de 32 bits. Las tablas de paginación luego traducen la dirección lineal de 32 bits en una dirección física de 36 bits (P-II). Existe protección en ambos pasos de traducción.
jonk
44
@flux su resumen es correcto. Un programa en un sistema de memoria protegido con un sistema operativo multitarea adecuado no debería poder bloquear el sistema con ninguna secuencia de instrucciones. Incluso los inválidos, esos terminan en un controlador especial.
pjc50
Aunque hay varios anillos (al menos en x86), es muy, muy raro que se utilicen más de dos.
bosque
10

Muchos sistemas operativos multitarea utilizan una estructura de datos llamada bloque de control de procesos (PCB) para solucionar el problema de sobrescritura de registros. Cuando ejecuta su código, el sistema operativo crea un nuevo proceso para realizar un seguimiento. El PCB contiene información sobre su proceso y el espacio asignado para contener el contenido del registro. Digamos que el proceso A se está ejecutando actualmente en el procesador y su código está en proceso B. Lo que sucede cuando ejecuta su código es algo así:

  1. Los datos de estado del proceso A (contenido del registro, contador del programa, etc.) se copian en su PCB.

  2. Los datos de estado del proceso B se copian de su PCB en los registros de la CPU

  3. El proceso B se ejecuta en el procesador hasta que finaliza o se adelanta

  4. Los datos de estado del proceso B se vuelven a copiar en su PCB

  5. Los datos de estado del proceso A se vuelven a copiar en la CPU y continúa ejecutándose

Si el sistema operativo se está ejecutando como el proceso A, puede ver cómo guardar sus registros antes de que se ejecute su programa y luego copiarlos nuevamente en la CPU una vez que finaliza su programa evita que los programas del usuario se enreden con lo que sucede en otros procesos.

Para evitar que los procesos del usuario escriban sobre los datos del sistema operativo en la memoria, la mayoría de las plataformas utilizan la segmentación de la memoria. Básicamente, utilizando la memoria virtual, el espacio de direcciones que ve un proceso puede asignarse a cualquier rango arbitrario de direcciones físicas. Mientras los espacios de memoria física de los procesos no se superpongan, es imposible que un proceso sobrescriba los datos de otro.

Por supuesto, los diferentes sistemas operativos hacen las cosas de manera diferente, por lo que esto no se aplicará en todos los casos. Además, en la mayoría de las plataformas, los procesos del sistema operativo se ejecutan en un modo diferente de los procesos del usuario y hay algunas complejidades allí.

jtst
fuente
4

Depende de la plataforma de la que estés hablando.

  • En un procesador más básico, el procesador solo ejecuta las instrucciones que el programa le dice que ejecute.

  • En un procesador más sofisticado, hay (al menos) dos modos. En un modo, el procesador hace lo que el programa le dice que haga. En el otro modo, el procesador se niega a ejecutar ciertas instrucciones.

¿Qué detiene un programa que bloquea todo el sistema? Con el primer tipo de procesador, la respuesta es "nada". Con un procesador básico, un solo programa no autorizado puede bloquear el sistema completo. Todas las primeras computadoras domésticas de 8 bits, y muchas de las de 16 bits, entran en esta categoría.

En una PC moderna, el procesador tiene hardware de "protección". Básicamente, el sistema operativo se ejecuta en un modo especial que le permite hacer cualquier cosa, mientras que los programas normales se ejecutan en un modo en el que el procesador solo permitirá ciertas acciones (según la configuración que el sistema operativo haya configurado en el procesador). Cosas como solo acceder a ciertos registros, o solo acceder a rangos de memoria particulares.

Obviamente, permitir que un solo programa malintencionado bloquee todo el sistema es malo. (También hay graves implicaciones de seguridad al permitir que un programa no autorizado acceda a los datos que desee). Para evitar esto, necesita dos cosas:

  1. Un procesador que realmente tiene hardware de protección (es decir, puede configurarse para negarse a ejecutar ciertas instrucciones).

  2. Un sistema operativo que realmente utiliza estas instalaciones para protegerse. (¡No es bueno tener un chip con circuitos de protección si el sistema operativo nunca lo usa!)

Casi cualquier SO de escritorio moderno que pueda nombrar (Windows, Linux, Mac OS, BSD ...) es un SO en modo protegido que se ejecuta en un procesador con hardware de protección. Si está realizando un desarrollo integrado en algún microcontrolador de 8 bits, probablemente no tenga ningún hardware de protección. (O cualquier sistema operativo, para el caso ...)

Orquídea matemática
fuente
1

P. ¿Qué impide que un programa de ensamblaje bloquee el sistema operativo?

A. nada.

Sin embargo, muchos programadores muy inteligentes se han esforzado mucho a lo largo de los años para hacerlo cada vez más difícil. Desafortunadamente, para cada programador inteligente, hay muchos, muchos otros que entre ellos son más creativos, más ambiciosos y, a veces, más afortunados que los inteligentes. Cada vez que un programador inteligente dice que nadie debería, haría o podría hacer algo, alguien por ahí encontrará la manera de hacerlo. Microsoft Windows (como ejemplo) ha existido durante casi 35 años y todavía tenemos BSoD (pantallas azules de la muerte), que son solo instrucciones que bloquearon el sistema operativo.

Comencemos con un poco de terminología. Todo lo que se ejecuta en una computadora lo hace en código máquina. El bit que lee las pulsaciones de teclas o el movimiento del puntero del mouse, el bit que cambia el color de un píxel en la pantalla o lee un byte de un archivo y el bit que calcula si su bala golpeó al tipo malo o al bit que decide si su solicitud de tarjeta de crédito será aceptada, todas se ejecutarán como una secuencia de instrucciones de código de máquina. Algunos trabajos son tan comunes y se realizan con tanta frecuencia que tiene sentido reunir las instrucciones necesarias para hacerlos y hacer que todos usen ese ensamblaje. El conjunto de estos trabajos que permiten o ayudan a otros a usar la computadora tienden a llamarse sistema operativo, pero no hay nada inherentemente diferente entre ellos y cualquier otro programa. Todos son solo secuencias de instrucciones de código de máquina.

Lo que hace que los sistemas operativos sean más complicados (y, por lo tanto, propensos a fallar) es que tienen que dar cuenta de cosas en las que normalmente no tiene que pensar. Tome los trabajos más simples como ejemplo. Quiero escribir un mensaje al final de un archivo. En un lenguaje de alto nivel escribirías algo como:

  with open("myFile.txt", "w+") as f:
      # do some really clever things
      f.write("Goodbye cruel world!")

Vamos a ignorar todos los detalles sobre cómo se accede y cambia los estados físicos o cómo se interpretan como bits y bytes o cómo esos bytes se transfieren hacia y desde la memoria y la CPU, y confíe en que todo eso es manejado por los programas que proporciona el sistema operativo entre bastidores. Solo pensemos en cómo se agrega al final de un archivo. 1) Averigüe dónde está el final del archivo, 2) escriba algo en esa posición. ¿Qué podría salir mal? En realidad, bastante. Piensa en qué más está sucediendo en la computadora mientras haces cosas inteligentes. Si cualquier otra cosa realizada por otra persona (incluido el propio sistema operativo) cambia el archivo en el que está trabajando de alguna manera, entonces este trabajo realmente simple de repente se vuelve mucho más complicado. El archivo es más largo, el archivo es más corto. El archivo ya no está allí. El disco está lleno,

Paul Smith
fuente