System Calls and Traps
See also system_calls
Overview
Calls to the system must cross the user-kernel protection barrier.
The barrier is hardware enforced. The i386 architecture has 4 levels
of protection, ring 0 through 3. Nt uses ring 0 for the kernel and
ring 3 for the user. The other rings are not used.
Call gates are flow-of-control constructs vectoring through the IDT.
According to the
software people, IDT stands for Interrupt Dispatch Table (see Solomon's
Inside Windows NT); according to the hardware people, it stands for Interrupt
Descriptor Table. This table is pointed to by a hardware register in the
I386 called the IDTR, the Interrupt Descriptor Table Register.
Call gates include the interrupt, the trap, the task gate and the call gate.
We are most interested here in the int 3 and int 2e traps. Traps differ
from interrupts in that interrupts disable all interrupts on occurance, traps
do not, hence leading to the situation of double-traps.
Are int 3 and int 2e traps or interrupts? Is a double trap an interrupt?
Is it the same as a double fault?
call gates
-
far pointers are 48 bits, 16 bits segment pointer and 32 bits offset.
-
a segment pointer points to a segment descriptor,
a 64 bit structure in either the LDT or GDT
-
the S bit in the segment descriptor identifies it as either a
code/data segment descriptor, or a system descriptor,
-
a system descriptor is identified in its type field as one of
16 different kinds, including a call gate.
-
a call w. to a far pointer, where the segment pointer points to a
call gate, invokes the call gate
-
a call gate includes the segment and offset for the new CS and EIP,
and so the offset given in the call instruction is ignored.
-
traps
-
interrupts and exceptions are referred to the IDT,
Interrupt Descriptor Table, whose base is set by the IDTR, a register.
-
there are 256 entries in the IDT, each a segment descriptor.
-
The segement descriptors allowed in the IDT are limited to task-gate,
interrupt-gate or trap-gate.
-
exceptions are either faults, traps or aborts.
a fault restarts at the faulting address.
a trap restarts and the following address.
an abort has no reliable restarting address.
-
interrupts are either internal or external. the external interrupts
are masked by EFLAGS.IF, the internal interrupts are not.
-
Interrupts clear the IF flag. Exceptions leave the IF flag unchanged.
Exhibits
The Details
The Interrupt Descriptor Table
should be seen in the context of two other tables, the Global Descriptor
Table and the Local Descriptor, in that each is a vector of Descriptors.
The descriptors of the IDT are Gate Descriptors. The GDT and LDT
can also hold segment descriptors. The GDT is pointed to by the
hardware register GDTR,
and the LDT is pointed to by the hardware register LDTR.
The gate descriptor format is:
- 16 bits selector
- 16 bit offset 15 ... 0
- 16 bit offset contiuned 31 ..16
- 16 bits of flags:
- P bit: 0 invalid/1 valid
- DPL (2 bits): descriptor privilege level
- one bit equal to 0
- Type (4 bits):
- 4 = i286 Call Gate
- 5 = i286/i486 Task Gate
- 6 = i286 Interrupt Gate
- 7 = i286 Trap Gate
- C = i486 Call Gate
- E = i486 Interrupt Gate
- F = i486 Trap Gate
- Byte of "word count" - lowest 5 bits are depth of call stack, in case
of a Call Gate only.
Given the little endianess of intel, here's a sample
entry with interpretation:
00084374 8014ee00
Flags are ee00, this is a valid, DPL level 3 (least privileged), i486 Interrupt Gate.
The target offset is 0x8014,4374, using selection 8.
Intel protection lets data access down towards less privileged segements and
gates upwards toward more privileged code. I do not know what the DPL level 3
indicates: for certain that anyone can vector through this trap. But now do
levels change?
These are virtual addresses.
The !pcr KD command will display the descriptor registers.
Apparantly the IDT is located staticly in kernel memroy around
0x80036400, at least its been seen twice at that location.
The following exhibit shows a remote kernel debug setup, with the
target halted by ^C.
Author
Burton Rosenberg
11:28 AM 9/28/98
Exhibits
-
KD Session
kd> !pcr
PCR Processor 0 @ffdff000
NtTib.ExceptionList: 8014f09c
NtTib.StackBase: 8014f380
NtTib.StackLimit: 8014c3f0
NtTib.SubSystemTib: 00000000
NtTib.Version: 00000000
NtTib.UserPointer: 00000000
NtTib.SelfTib: 00000000
SelfPcr: ffdff000
Prcb: ffdff120
Irql: 0000001c
IRR: 00000000
IDR: ffff22e8
InterruptMode: 00000000
IDT: 80036400
GDT: 80036000
TSS: 8001d000
CurrentThread: 8014c1b0
NextThread: 00000000
IdleThread: 8014c1b0
*** Bad IOCTL request from an extension [1]
kd> dd 0x80036400
80036400 00083f64 80148e00 000840ac 80148e00
80036410 005812de 00008500 00084374 8014ee00
80036420 000844c8 8014ee00 00084604 80148e00
80036430 0008475c 80148e00 00084c78 80148e00
80036440 00501338 00008500 00084fb8 80148e00
80036450 000850b8 80148e00 000851dc 80148e00
80036460 000854cc 80148e00 000856cc 80148e00
80036470 00086078 80148e00 000863e4 80148e00
kd> u 0x080144374
ntoskrnl!KiTrap03:
80144374 6a00 push 0x0
80144376 66c74424020000 mov word ptr [esp+0x2],0x0
8014437d 55 push ebp
8014437e 53 push ebx
8014437f 56 push esi
80144380 57 push edi
80144381 0fa0 push fs
80144383 bb30000000 mov ebx,0x30
kd>
-
Interrupt Descriptor Table
Either !pcr
or the r idtr
can be used to find the IDT's location.
The format of the selectors (gates), when displayed as two double words, is:
[segment sel | offset 15..0 ] [ offset 31:16 | info ]
where info is:
P:1 DPL:2 (00101 | 0D110 | 0D111) 0x00
where P is 1 if Present, DPL is the Descriptor Privlege Level,
D is 1 for a 32 bit gate, 0 for a 16 bit gate (?), and
110 signals an interupt gate, or 111 signals a trap gate, or 101 a task gate.
kd> dd idtr
80036400 00085034 80148e00 0008517c 80148e00
80036410 005812de 00008500 00085444 8014ee00
80036420 00085598 8014ee00 000856d4 80148e00
80036430 0008582c 80148e00 00085d48 80148e00
80036440 00501338 00008500 00086088 80148e00
80036450 00086188 80148e00 000862ac 80148e00
80036460 0008659c 80148e00 0008679c 80148e00
80036470 00087194 80148e00 00087528 80148e00
kd> dd
80036480 00087628 80148e00 0008773c 80148e00
80036490 00a07528 80148500 00087528 80148e00
800364a0 00087528 80148e00 00087528 80148e00
800364b0 00087528 80148e00 00087528 80148e00
800364c0 00087528 80148e00 00087528 80148e00
800364d0 00087528 80148e00 00087528 80148e00
800364e0 00087528 80148e00 00087528 80148e00
800364f0 00087528 80148e00 00087528 80148e00
kd> dd
80036500 00080000 00000000 00080000 00000000
80036510 00080000 00000000 00080000 00000000
80036520 00080000 00000000 00080000 00000000
80036530 00080000 00000000 00080000 00000000
80036540 00080000 00000000 00080000 00000000
80036550 00084586 8014ee00 00084670 8014ee00
80036560 00084780 8014ee00 0008533c 8014ee00
80036570 00084100 8014ee00 00087528 80148e00
kd> dd
80036580 00084ffc 80018e00 00087b44 80678e00
80036590 00083844 80148e00 0008384e 80148e00
800365a0 00089dc4 805f8e00 00083862 80148e00
800365b0 0008386c 80148e00 00083876 80148e00
800365c0 00080a18 80018e00 0008388a 80148e00
800365d0 00080ba4 80628e00 00080a84 806f8e00
800365e0 00087dc4 80678e00 000838b2 80148e00
800365f0 00081dc4 806e8e00 00081404 806f8e00