Una puerta de llamada es un mecanismo en la arquitectura x86 de Intel para cambiar el nivel de privilegio de un proceso cuando ejecuta una llamada de función predefinida usando una instrucción CALL FAR.
Descripción general
Las puertas de llamada están diseñadas para permitir que el código menos privilegiado llame al código con un nivel de privilegio más alto. Este tipo de mecanismo es esencial en los sistemas operativos modernos que emplean protección de memoria, ya que permite que las aplicaciones de usuario usen funciones del kernel y llamadas al sistema de una manera que puede ser controlada por el sistema operativo .
Las puertas de llamada utilizan un valor selector especial para hacer referencia a un descriptor al que se accede mediante la Tabla de descriptores globales o la Tabla de descriptores locales , que contiene la información necesaria para la llamada a través de los límites de privilegios. Es similar al mecanismo utilizado para las interrupciones .
Uso
Suponiendo que el kernel del sistema operativo ya ha configurado una puerta de llamada , el código simplemente hace una CALL FAR con el selector de segmento necesario (el campo de compensación se ignora). El procesador realizará una serie de comprobaciones para asegurarse de que la entrada sea válida y que el código esté funcionando con privilegios suficientes para usar la puerta. Suponiendo que todas las comprobaciones pasan, se carga un nuevo CS / EIP desde el descriptor de segmento y la información de continuación se envía a la pila del nuevo nivel de privilegio (SS antiguo, ESP antiguo, CS antiguo, EIP antiguo, en ese orden). Los parámetros también se pueden copiar de la pila antigua a la pila nueva si es necesario. El número de parámetros a copiar se encuentra en el descriptor de puerta de llamada.
El kernel puede regresar al programa de espacio de usuario usando una instrucción RET FAR que saca la información de continuación de la pila y regresa al nivel de privilegio externo.
Formato del descriptor de puerta de llamada
typedef struct _CALL_GATE { USHORT OffsetLow ; Selector de USHORT ; UCHAR NumberOfArguments : 5 ; UCHAR Reservado : 3 ; Tipo UCHAR : 5 ; // 01100 en i386, 00100 en i286 UCHAR Dpl : 2 ; UCHAR Presente : 1 ; USHORT OffsetHigh ; } CALL_GATE , * PCALL_GATE ;
Uso anterior
Multics fue el primer usuario de puertas de llamada. El Honeywell 6180 tenía puertas de llamada como parte de la arquitectura, pero Multics las simuló en el GE 645 más antiguo .
OS / 2 fue uno de los primeros usuarios de las puertas de llamada de Intel para transferir entre el código de la aplicación que se ejecuta en el anillo 3, el código privilegiado que se ejecuta en el anillo 2 y el código del núcleo en el anillo 0.
Windows 95 ejecuta los controladores y el cambio de procesos en el anillo 0, mientras que las aplicaciones, incluidas las API DLL, como kernel32.dll y krnl386.exe, se ejecutan en el anillo 3. El controlador VWIN32.VXD proporciona primitivas clave del sistema operativo en el anillo 0. Permite llamar al controlador funciones de aplicaciones de 16 bits (MSDOS y Win16). Esta dirección se obtiene llamando a INT 2Fh, con 1684h en el registro AX. Para identificar para qué VxD se solicita un punto de entrada, el registro BX se establece en el ID de VxD de 16 bits. Al regresar de la instrucción INT, los registros ES.DI contienen un puntero lejano que se puede llamar para transferir el control al VxD que se ejecuta en el anillo 0. El descriptor señalado por ES es en realidad la puerta de llamada. [1] Las aplicaciones de 32 bits, sin embargo, cuando necesitan acceder al código del controlador de Windows 95, llaman a la función VxDCall no documentada en KERNEL32.DLL que esencialmente llama a INT 30h, que cambia el modo de timbre.
Uso moderno
Los sistemas operativos x86 modernos se están alejando de las puertas de llamada CALL FAR. Con la introducción de instrucciones x86 para llamadas al sistema (SYSENTER / SYSEXIT de Intel y SYSCALL / SYSRET de AMD), se introdujo un nuevo mecanismo más rápido para transferencias de control para programas x86. Como la mayoría de las otras arquitecturas no admiten puertas de llamada, su uso era poco común incluso antes de estas nuevas instrucciones, ya que se preferían las interrupciones o trampas de software para la portabilidad, aunque las puertas de llamada son significativamente más rápidas que las interrupciones.
Las puertas de llamada son más flexibles que las instrucciones SYSENTER / SYSEXIT y SYSCALL / SYSRET ya que, a diferencia de las dos últimas, las puertas de llamada permiten cambiar de un nivel de privilegio arbitrario a un nivel de privilegio arbitrario (aunque mayor o igual). Las instrucciones rápidas SYS * solo permiten transferencias de control del anillo 3 al 0 y viceversa.
Temas de seguridad
Para preservar la seguridad del sistema, la Tabla de descriptores globales debe mantenerse en la memoria protegida; de lo contrario, cualquier programa podrá crear su propia puerta de llamada y usarla para aumentar su nivel de privilegios. Las puertas de llamada se han utilizado en exploits de seguridad de software , cuando se han encontrado formas de evitar esta protección. [2] Un ejemplo de esto es el gusano de correo electrónico Gurong.A , escrito para explotar el sistema operativo Microsoft Windows , que usa \ Device \ PhysicalMemory para instalar una puerta de llamada. [3]
Ver también
Referencias
- ^ Matt Pietrek , Secretos de programación del sistema Windows 95
- ^ El blog del proyecto Xen de escalada de privilegios Intel SYSRET
- ^ Gusano: W32 / Gurong.A Descripción F-Secure Labs