Call gate (Intel)
This article needs additional citations for verification. (August 2020) |
A call gate is a mechanism in Intel's x86 architecture for changing the privilege level of a process when it executes a predefined function call using a CALL FAR instruction.
Overview
[edit]Call gates are intended to allow less privileged code to call code with a higher privilege level. This type of mechanism is essential in modern operating systems that employ memory protection since it allows user applications to use kernel functions and system calls in a way that can be controlled by the operating system.
Call gates use a special selector value to reference a descriptor accessed via the Global Descriptor Table or the Local Descriptor Table, which contains the information needed for the call across privilege boundaries. This is similar to the mechanism used for interrupts.
Usage
[edit]Assuming a call gate has been set up already by the operating system kernel, code simply does a CALL FAR with the necessary segment selector (the offset field is ignored). The processor will perform a number of checks to make sure the entry is valid and the code was operating at sufficient privilege to use the gate. Assuming all checks pass, a new CS/EIP is loaded from the segment descriptor, and continuation information is pushed onto the stack of the new privilege level (old SS, old ESP, old CS, old EIP, in that order). Parameters may also be copied from the old stack to the new stack if needed. The number of parameters to copy is located in the call gate descriptor.
The kernel may return to the user space program by using a RET FAR instruction which pops the continuation information off the stack and returns to the outer privilege level.
Format of call gate descriptor
[edit]typedef struct _CALL_GATE
{
USHORT OffsetLow;
USHORT Selector;
UCHAR NumberOfArguments:5;
UCHAR Reserved:3;
UCHAR Type:5; // 01100 in i386, 00100 in i286
UCHAR Dpl:2;
UCHAR Present:1;
USHORT OffsetHigh;
}CALL_GATE,*PCALL_GATE;
Previous use
[edit]Multics was the first user of call gates. The Honeywell 6180 had call gates as part of the architecture, but Multics simulated them on the older GE 645.
OS/2 was an early user of Intel call gates to transfer between application code running in ring 3, privileged code running in ring 2, and kernel code in ring 0.
Windows 95 executes drivers and process switching in ring 0, while applications, including API DLL such as kernel32.dll and krnl386.exe are executed in ring 3. Driver VWIN32.VXD provides key operating system primitives at ring 0. It allows calling of driver functions from 16-bit applications (MSDOS and Win16). This address is obtained by calling INT 2Fh, with 1684h in the AX register. To identify which VxD an entry point is being requested for, the BX register is set to the 16-bit VxD ID. Upon return from the INT instruction, the ES.DI registers contain a far pointer that can be called to transfer control to the VxD running at ring 0. The descriptor pointed by ES is actually a call gate.[1] 32-bit applications, however, when they need to access Windows 95 driver code, call undocumented VxDCall function in KERNEL32.DLL which essentially calls INT 30h, which changes ring mode.
Modern use
[edit]Modern x86 operating systems are transitioning away from CALL FAR call gates. With the introduction of x86 instructions for system call (SYSENTER/SYSEXIT by Intel and SYSCALL/SYSRET by AMD), a new faster mechanism was introduced for control transfers for x86 programs. As most other architectures do not support call gates, their use was rare even before these new instructions, as software interrupts or traps were preferred for portability, even though call gates are significantly faster than interrupts.
Call gates are more flexible than the SYSENTER/SYSEXIT and SYSCALL/SYSRET instructions since unlike the latter two, call gates allow for changing from an arbitrary privilege level to an arbitrary (albeit higher or equal) privilege level. The fast SYS* instructions only allow control transfers from ring 3 to 0 and vice versa.
Security issues
[edit]To preserve system security, the Global Descriptor Table must be held in protected memory, otherwise any program will be able to create its own call gate and use it to raise its privilege level. Call gates have been used in software security exploits, when ways have been found around this protection.[2] One example of this is the e-mail worm Gurong.A, written to exploit the Microsoft Windows operating system, which uses \Device\PhysicalMemory to install a call gate.[3]
See also
[edit]References
[edit]- ^ Matt Pietrek, Windows 95 System Programming Secrets
- ^ The Intel SYSRET privilege escalation Xen Project Blog
- ^ Worm:W32/Gurong.A Description F-Secure Labs