Protección de memoria
protección de la memoria es una forma de controlar los derechos de acceso a la memoria en una computadora y es parte de la mayoría de las arquitecturas de conjuntos de instrucciones y sistemas operativos modernos. El objetivo principal de la protección de la memoria es evitar que un proceso acceda a la memoria que no le ha sido asignada. Esto evita que un error o malware dentro de un proceso afecte a otros procesos o al propio sistema operativo. La protección puede abarcar todos los accesos a un área específica de memoria, accesos de escritura o intentos de ejecutar el contenido del área. Un intento de acceder a la memoria no autorizada da como resultado una falla de hardware, por ejemplo, una falla de segmentación, una excepción de violación de almacenamiento, que generalmente causa una terminación anormal del proceso infractor. La protección de la memoria para la seguridad informática incluye técnicas adicionales como la aleatorización del diseño del espacio de direcciones y la protección del espacio ejecutable.
Métodos
Segmentación
La segmentación se refiere a dividir la memoria de una computadora en segmentos. Una referencia a una ubicación de memoria incluye un valor que identifica un segmento y un desplazamiento dentro de ese segmento. Un descriptor de segmento puede limitar los derechos de acceso, por ejemplo, solo lectura, solo desde ciertos anillos.
La arquitectura x86 tiene múltiples funciones de segmentación, que son útiles para usar memoria protegida en esta arquitectura. En la arquitectura x86, la tabla de descriptores globales y las tablas de descriptores locales se pueden utilizar para hacer referencia a segmentos en la memoria de la computadora. Los punteros a segmentos de memoria en procesadores x86 también se pueden almacenar en los registros de segmento del procesador. Inicialmente los procesadores x86 tenían 4 registros de segmento, CS (segmento de código), SS (segmento de pila), DS (segmento de datos) y ES (segmento extra); Posteriormente se agregaron otros dos registros de segmento: FS y GS.
Memoria virtual paginada
En la paginación, el espacio o segmento de direcciones de memoria se divide en bloques del mismo tamaño llamados páginas. Al utilizar hardware de memoria virtual, cada página puede residir en cualquier ubicación en un límite adecuado de la memoria física de la computadora o marcarse como protegida. La memoria virtual permite tener un espacio de direcciones de memoria virtual lineal y utilizarlo para acceder a bloques fragmentados en el espacio de direcciones de la memoria física.
La mayoría de las arquitecturas informáticas que admiten paginación también utilizan páginas como base para la protección de la memoria.
Una tabla de páginas asigna la memoria virtual a la memoria física. Puede haber una tabla de páginas única, una tabla de páginas para cada proceso, una tabla de páginas para cada segmento o una jerarquía de tablas de páginas, según la arquitectura y el sistema operativo. Las tablas de páginas suelen ser invisibles para el proceso. Las tablas de páginas facilitan la asignación de memoria adicional, ya que cada página nueva se puede asignar desde cualquier lugar de la memoria física. En algunos sistemas, una entrada de la tabla de páginas también puede designar una página como de solo lectura.
Algunos sistemas operativos configuran un espacio de direcciones diferente para cada proceso, lo que proporciona límites de protección de la memoria dura. Es imposible que una aplicación sin privilegios acceda a una página que no se le ha asignado explícitamente, porque cada dirección de memoria apunta a una página asignada a esa aplicación o genera una interrupción llamada fallo de página. Las páginas no asignadas y las páginas asignadas a cualquier otra aplicación no tienen direcciones desde el punto de vista de la aplicación.
Un error de página no necesariamente indica un error. Los errores de página no sólo se utilizan para proteger la memoria. El sistema operativo puede gestionar la tabla de páginas de tal manera que una referencia a una página que se ha paginado previamente al almacenamiento secundario provoque un error de página. El sistema operativo intercepta el error de la página, carga la página de memoria requerida y la aplicación continúa como si no hubiera ocurrido ningún error. Este esquema, un tipo de memoria virtual, permite que los datos en memoria que no están en uso actualmente se muevan al almacenamiento secundario y regresen de una manera que sea transparente para las aplicaciones, para aumentar la capacidad general de la memoria.
En algunos sistemas, una solicitud de almacenamiento virtual puede asignar un bloque de direcciones virtuales para las cuales no se han asignado marcos de página, y el sistema solo asignará e inicializará marcos de página cuando ocurran fallas en la página. En algunos sistemas se puede utilizar una página de protección, ya sea para la detección de errores o para hacer crecer automáticamente las estructuras de datos.
En algunos sistemas, el mecanismo de error de página también se utiliza para la protección del espacio ejecutable, como W^X.
Teclas de protección
Un mecanismo de clave de protección de memoria (MPK) divide la memoria física en bloques de un tamaño particular (por ejemplo, 4 kiB), cada uno de los cuales tiene un valor numérico asociado llamado clave de protección. Cada proceso también tiene un valor de clave de protección asociado. En un acceso a la memoria, el hardware verifica que la clave de protección del proceso actual coincida con el valor asociado con el bloque de memoria al que se accede; si no, se produce una excepción. Este mecanismo se introdujo en la arquitectura System/360. Está disponible en los mainframes System z actuales y es muy utilizado por los sistemas operativos System z y sus subsistemas.
Las claves de protección de System/360 descritas anteriormente están asociadas con direcciones físicas. Esto es diferente del mecanismo de clave de protección utilizado por arquitecturas como Hewlett-Packard/Intel IA-64 y Hewlett-Packard PA-RISC, que están asociadas con direcciones virtuales y que permiten múltiples claves por proceso.
En las arquitecturas Itanium y PA-RISC, las traducciones (entradas TLB) tienen claves (Itanium) o identificadores de acceso (PA-RISC) asociados. Un proceso en ejecución tiene varios registros de claves de protección (16 para Itanium, 4 para PA-RISC). Una traducción seleccionada por la dirección virtual tiene su clave comparada con cada uno de los registros de claves de protección. Si alguno de ellos coincide (más otras posibles comprobaciones), se permite el acceso. Si ninguno coincide, se genera una falla o excepción. El manejador de fallas de software puede, si lo desea, comparar la clave que falta con una lista más grande de claves mantenidas por el software; por lo tanto, los registros de claves de protección dentro del procesador pueden tratarse como una caché administrada por software de una lista más grande de claves asociadas con un proceso.
PA-RISC tiene entre 15 y 18 bits de clave; Itanium exige al menos 18. Las claves generalmente están asociadas con dominios de protección, como bibliotecas, módulos, etc.
En x86, la arquitectura de claves de protección permite etiquetar direcciones virtuales para páginas de usuario con cualquiera de las 16 claves de protección. Todas las páginas etiquetadas con la misma clave de protección constituyen un dominio de protección. Un nuevo registro contiene los permisos asociados con cada uno de los dominios de protección. Las operaciones de carga y almacenamiento se comparan con los permisos de la tabla de páginas y los permisos de la clave de protección asociados con el dominio de protección de la dirección virtual, y solo se permiten si ambos permisos permiten el acceso. Los permisos de la clave de protección se pueden configurar desde el espacio del usuario, lo que permite que las aplicaciones restrinjan directamente el acceso a los datos de la aplicación sin intervención del sistema operativo. Dado que las claves de protección están asociadas con una dirección virtual, los dominios de protección son por espacio de direcciones, por lo que los procesos que se ejecutan en diferentes espacios de direcciones pueden usar cada uno de los 16 dominios.
Anillos de protección
En Multics y sistemas derivados de él, cada segmento tiene un anillo de protección para lectura, escritura y ejecución; un intento de un proceso con un número de timbre mayor que el número de timbre del segmento provoca una falla. Existe un mecanismo para llamar de forma segura a procedimientos que se ejecutan en un anillo inferior y regresar al anillo superior. Existen mecanismos para que una rutina que se ejecuta con un número de timbre bajo acceda a un parámetro con el mayor entre su propio timbre y el timbre de la persona que llama.
Segmentación simulada
La simulación es el uso de un programa de monitoreo para interpretar las instrucciones del código de máquina de algunas arquitecturas informáticas. Un simulador de conjunto de instrucciones de este tipo puede proporcionar protección de la memoria mediante el uso de un esquema similar a la segmentación y la validación de la dirección de destino y la longitud de cada instrucción en tiempo real antes de ejecutarlas. El simulador debe calcular la dirección y la longitud de destino y compararlos con una lista de rangos de direcciones válidos que contiene en relación con el entorno del subproceso, como cualquier bloque de memoria dinámica adquirido desde el inicio del subproceso, además de cualquier Ranuras de memoria estática compartida. El significado de "válido" puede cambiar a lo largo de la vida del hilo dependiendo del contexto. A veces se le puede permitir alterar un bloque estático de almacenamiento y otras no, dependiendo del modo de ejecución actual, que puede depender o no de una clave de almacenamiento o del estado del supervisor.
Por lo general, no es recomendable utilizar este método de protección de la memoria cuando existen instalaciones adecuadas en una CPU, ya que esto consume una valiosa potencia de procesamiento de la computadora. Sin embargo, generalmente se utiliza con fines de depuración y prueba para proporcionar un nivel extra fino de granularidad a violaciones de almacenamiento genéricas y puede indicar con precisión qué instrucción intenta sobrescribir la sección particular de almacenamiento que puede tener la misma clave de almacenamiento que el almacenamiento no protegido.
Direccionamiento basado en capacidad
El direccionamiento basado en capacidad es un método de protección de la memoria que no se utiliza en las computadoras comerciales modernas. En este método, los punteros se reemplazan por objetos protegidos (llamados capacidades) que solo se pueden crear usando instrucciones privilegiadas que solo pueden ser ejecutadas por el kernel o algún otro proceso autorizado para hacerlo. Esto permite efectivamente que el kernel controle qué procesos pueden acceder a qué objetos en la memoria, sin necesidad de utilizar espacios de direcciones separados o cambios de contexto. Sólo unos pocos productos comerciales utilizaban seguridad basada en capacidades: Plessey System 250, IBM System/38, arquitectura Intel iAPX 432 y KeyKOS. Los enfoques de capacidad se utilizan ampliamente en sistemas de investigación como EROS y el navegador Combex DARPA. Se utilizan conceptualmente como base para algunas máquinas virtuales, sobre todo Smalltalk y Java. Actualmente, el proyecto CHERI de la Universidad de Cambridge, financiado por DARPA, está trabajando para crear una máquina moderna que también admita software heredado.
Contaminación dinámica
La contaminación dinámica es una técnica para proteger programas de accesos ilegales a la memoria. Cuando se asigna memoria, en tiempo de ejecución, esta técnica contamina tanto la memoria como el puntero correspondiente utilizando la misma marca de contaminación. Luego, las marcas de contaminación se propagan adecuadamente mientras se ejecuta el programa y se verifican cada vez que se accede a una dirección de memoria m a través de un puntero p; Si las marcas de corrupción asociadas con m y p difieren, se detiene la ejecución y se informa el acceso ilegal.
Los procesadores SPARC M7 (y superiores) implementan contaminación dinámica en el hardware. Oracle comercializa esta característica como Silicon Secured Memory (SSM) (anteriormente denominada Application Data Integrity (ADI)).
El diseño de la CPU lowRISC incluye contaminación dinámica bajo el nombre Tagged Memory.
Medidas
El nivel de protección de una implementación particular puede medirse por qué tan estrechamente se adhiere al principio de privilegio mínimo.
Protección de la memoria en diferentes sistemas operativos
Los diferentes sistemas operativos utilizan diferentes formas de protección o separación de la memoria. Aunque la protección de la memoria era común en la mayoría de las computadoras centrales y en muchos sistemas de minicomputadoras desde la década de 1960, la verdadera separación de memoria no se usó en los sistemas operativos de las computadoras domésticas hasta que se lanzó OS/2 (y en RISC OS) en 1987. En los sistemas anteriores, tal falta de protección Incluso se utilizó como una forma de comunicación entre procesos, mediante el envío de un puntero entre procesos. Es posible que los procesos accedan a la memoria del sistema en la familia de sistemas operativos Windows 9x.
Algunos sistemas operativos que implementan protección de memoria incluyen:
- Sistemas similares a seis (desde finales de los años 70), incluyendo Solaris, Linux, BSD, macOS, iOS y GNU Hurd
- Plan9 e Inferno, creado en Bell Labs como sucesores Unix (1992, 1995)
- OS/2 (1987)
- RISC OS (1987) (La protección de la memoria OS no es completa.)
- Microware OS-9, como módulo opcional (desde 1992)
- Microsoft Windows familia de Windows NT 3.1 (1993)
- Atari MultiTOS (desde 1991)
- Pharos (desde 2017)
En sistemas tipo Unix, la llamada al sistema mprotect
se utiliza para controlar la protección de la memoria.