Call Gate

The Problem

Assume that the OS includes a code segment residing at privilege level zero (the most privileged level) containing a number of procedures to handle requests from other programs. Also assume that some of the procedures within this code segment should only be accessible by programs residing at privilege levels one and two. Any attempt to call one of these procedures in this code segment by a program residing at privilege level three (an applications program) should be rejected (i.e., should cause a GP exception). Also assume that some other procedures within the same OS code segment are designed to handle requests from applications programs (privilege level three).

The problem is that the code segment has one privilege level, zero, which means that all procedures within this code segment execute at privilege level zero. Ordinarily, any attempt to transfer control to (i.e., call or jump to) one of these routines from a program operating at another privilege level would result in a GP exception. Making it a conforming code segment isn't the answer because all procedures within this code segment could then be successfully called by programs with lower privilege levels.

The Solution—Different Gateways

The solution is to define a separate gateway to control access to each procedure within the code segment. Each gateway would contain the entry point of its associated procedure and would limit access to the procedure based on the privilege level of the caller. It would reject access attempts by any program whose privilege level does not match its criteria and permit access attempts by programs that meet the criteria. These gateways are referred to as Call Gates.

A Call Gate is a special form of OS descriptor and may reside in either the GDT or LDT. It may not reside within the Interrupt Descriptor Table (IDT). A Call Gate is used to transfer control to a procedure whose privilege level is the same as or more privileged than the calling program.

  • Only far CALL instructions can use Call Gates to transfer control to procedures with a more privileged level than their own.

  • Jump instructions can use Call Gates to transfer control to procedures with either the same privilege level or to a conforming code segment with a more privileged level.

A Call Gate descriptor basically contains an indirect pointer to a code segment and an entry point (i.e., an offset) within it. To access a Call Gate, the programmer executes a far CALL or a far jump instruction, thereby loading a 16-bit value into the CS register. The CS value identifies the GDT or LDT entry containing the Call Gate descriptor. The offset portion of the called address is discarded.

The format of a Call Gate descriptor is illustrated in Figure 8-5 on page 145. It consists of the elements described in Table 8-3 on page 144.

Table 8-3. Call Gate Descriptor Elements
FieldDescription
PSegment Present bit.
  • 0 = descriptor contents not valid.

  • 1 = contents valid.

DPLDescriptor Privilege Level.
SS = 0 because a Call Gate is a System descriptor type.
X
  • 0 = 16-bit Call Gate (formatted for the 286 processor). A 16-bit Call Gate descriptor exhibits the following differences from a 32-bit Call Gate descriptor:

    - The Count field indicates words rather than dwords.

    - Bytes 6 and 7 are reserved (in other words, the offset is a 16- rather than a 32-bit value).

  • 1 = 32-bit Call Gate (formatted for the post-286 processors).

Byte 5, [2:0]Contains 100b. Combined with S = 0, identifies this as a Call Gate descriptor. Bit [3] of byte 5 further identifies whether this is a 16- or a 32-bit Call Gate.
Dword CountIn a 32-bit Call Gate descriptor, tells processor how many dwords to copy from the caller's stack to the stack of the called procedure (see section entitled “Automatic Stack Switch” on page 153).
SelectorIdentifies the code segment descriptor that contains the base address of the code segment that the called procedure resides within.
OffsetIdentifies the offset of the called procedure's entry point within the target code segment (see the previous row).

Figure 8-5. 32-bit Call Gate Descriptor Format


Call Gate Example

Execution Begins

Now assume that the following instruction is executed by an applications program (in other words, a program executing at privilege level three):

call 0067:0000    ;call a privilege level 0 procedure
                  ;through the Call Gate in entry 12d
                  ;of the currently executing program's
                  ;LDT

Before permitting the call to take place, the processor must determine if this is a far CALL directly to a code segment or a call through a Call Gate descriptor. To do this, the processor reads the segment descriptor identified by the segment portion of the target address placed into the CS register. Figure 8-6 on page 146 illustrates the 16-bit value placed into the CS by the CALL instruction (0067h). This selects entry 12d (the index field contains Ch—12d) in the LDT (TI=1).

Figure 8-6. CS Contents During Call through Example Call Gate


Call Gate Descriptor Read

The descriptor read from entry 12d in the LDT is pictured in Figure 8-7 on page 147. The processor examines the S bit and the segment Type field to determine the type of descriptor:

  • S = 0, indicating that it is a special system segment.

  • Type = 1100b, indicating that it is a 32-bit Call Gate descriptor.

Figure 8-7. Example Call Gate Descriptor


Table 8-4 on page 146 provides a breakdown of the Call Gate descriptor's contents.

Table 8-4. Elements of the Example Call Gate Descriptor (see Figure 8-7)
FieldLocationDescription
PByte 5, bit 7P = 1, indicating that the descriptor is valid.
DPLByte 5, bits [6:5]DPL = 11b (3). Defines the minimum privilege level the caller must have to use the gate. In this case, any program with any privilege level (0, 1, 2, or 3) can use the gate without causing an exception. The value compared to the DPL is the less-privileged of the caller's CPL and RPL. Read the section entitled “The Call Gate Privilege Check” on page 151 for more information.
SByte 5, bit 4S = 0, indicating that this is a special system segment (see the next row).
TypeByte 5, bits [3:0]S = 0 indicates that this is a special, system segment, and Type = 1100b indicates that it is a 32-bit Call Gate (formatted for the post-286 processors).
Dword CountByte 4, bits [4:0]Dword Count = 00010b, indicating that 2 dwords are to be copied from the caller's stack to the called procedure's stack.
SelectorBytes 2 and 3Selector = 0150h, indicating that the target code segment's descriptor is entry 42d of the GDT. The RPL portion has no significance.
OffsetBytes 0, 1, 6, 7The offset = 00003400h, indicating that the procedure being called starts at location 00003400h in the target code segment.

Call Gate Contains Code Segment Selector

Table 8-4 on page 146 and Figure 8-7 on page 147 illustrate the code segment selector found in the Call Gate descriptor. Figure 8-8 on page 148 shows the selector divided into its component fields. The descriptor for the code segment containing the target procedure is in entry 42d of the GDT.

Figure 8-8. Code Segment Selector Specified in Example Call Gate


Code Segment Descriptor Read

The processor reads the CS descriptor from entry 42d in the GDT. The descriptor is pictured in Figure 8-9 on page 150 and its elements are identified in Table 8-5 on page 148.

Figure 8-9. Example Code Segment Descriptor


Table 8-5. Example Code Segment Descriptor
FieldLocationDescription
GByte 6, bit 7G = 0, indicating that the 20-bit limit (i.e., CS size) is expressed in bytes rather than in 4KB pages.
DByte 6, bit 6D = 1, indicating that this is a post-286, 32-bit code segment.
AvlByte 6, bit 5Avl = 0. This is an OS-specific bit and has no meaning to the processor.
PByte 5, bit 7P = 1, indicating that the descriptor is valid and the code segment is present in memory.
DPLByte 5, bits [6:5]DPL of the code segment = 3 (the least privileged level). See the section entitled “The Call Gate Privilege Check” on page 151 for more information.
SByte 5, bit 4S = 1, indicating that this is not a special, system segment.
C/DByte 5, bit 3C/D = 1, indicating that this is a code rather than a data or a stack segment.
CByte 5, bit 2C = 0, indicating that this is a non-conforming code segment. See the section entitled “Conforming and Non-Conforming Code Segments” on page 141 for more information.
RByte 5, bit 1R = 0, indicating that this is an execute-only code segment.
AByte 5, bit 0A = 1, indicating that the code segment has been accessed since it was placed in memory.
BaseBytes 2, 3, 4, 732-bit base address of code segment = 00131BCCh.
LimitByte 0, 1, and bits [3:0] of byte 6Segment length = 1EE3Dh (126,525d bytes).

The Big Picture

Figure 8-10 on page 151 illustrates the overall relationship of the instruction, the Call Gate, the code segment descriptor and the called procedure.

Figure 8-10. Call Gate and CS Descriptors, Code Segment and Called Procedure


The Call Gate Privilege Check

Privilege Check for a Call through a Call Gate

A Call Gate may be used to transfer execution to a more privileged code segment or to a code segment with the same privilege level (although it's not necessary when transferring execution to a code segment with the same privilege level).

When executing a CALL through a Call Gate, a GP exception is generated unless both of the following tests are passed:

  1. The numerically greater of (i.e., the lesser privileged of) the CPL and RPL must be numerically <= the Call Gate's DPL. The Call Gate descriptor's DPL defines the minimum level of privilege a caller must have to use the gate. The value compared to the DPL is the lesser-privileged of the caller's RPL and CPL.

    As an example, a Call Gate descriptor with a DPL = 2 can be used by callers with privilege levels of zero, one, or two. Any attempt by a caller with a privilege level of three results in a GP exception.

  2. The destination code segment's DPL must be numerically <= the CPL. The caller's CPL must be the same as or less-privileged than the target code segment descriptor's DPL. In other words, using the Call Gate, the targeted code segment may be called by any program that doesn't have a higher privilege level than the target code segment's DPL.

As an example, if the code segment descriptor's DPL = 1, it can be called by programs with a privilege level of one, two, or three using a Call Gate. An attempt by a program with a privilege level of zero to call this code segment using a Call Gate results in a GP exception.

Privilege Check for a Jump through a Call Gate

Unlike a call, a jump cannot use a Call Gate to jump to a code segment that is more privileged. The target of the jump may be in either a conforming or a non-conforming code segment. The following paragraphs define the access rules for both cases.

When executing a jump through a Call Gate to a non-conforming code segment, a GP exception is generated unless both of the following tests are passed:

  1. The numerically greater of the CPL and RPL must be numerically <= the Call Gate's DPL. The Call Gate descriptor's DPL defines the minimum level of privilege the program executing the jump must have to use the gate. The value compared to the DPL is the lesser-privileged of the jumper's RPL and CPL. As an example, a Call Gate descriptor with a DPL = 2 can be used by jumpers with privilege levels of zero, one, or two. Any attempt by a jumper with a privilege level of three results in a GP exception.

  2. The destination code segment's DPL must = the CPL. In other words, the program attempting to jump to the destination code segment must have the same privilege level as the destination code segment.

When executing a jump through a Call Gate to a conforming code segment, a GP exception is generated unless both of the following tests are passed:

  1. The numerically greater of the CPL and RPL must be numerically <= the Call Gate's DPL. The Call Gate descriptor's DPL defines the minimum level of privilege a jumper must have to use the gate. The value compared to the DPL is the lesser-privileged of the jumper's RPL and CPL.

    As an example, a Call Gate descriptor with a DPL = 2 can be used by jumpers with privilege levels of zero, one, or two. Any attempt by a jumper with a privilege level of three results in a GP exception.

  2. The destination code segment's DPL must be numerically <= CPL. The jumper's CPL must be the same as or less-privileged than the target code segment descriptor's DPL. In other words, the code segment may be jumped to via the Call Gate by any program that doesn't have a higher privilege level than the target code segment's DPL.

As an example, if the code segment descriptor's DPL = 1, it can be jumped to using a Call Gate by programs with a privilege level of one, two, or three. An attempt by a program with a privilege level of zero to jump to this code segment using a Call Gate results in a GP exception.

Automatic Stack Switch

A CALL instruction automatically saves a pointer to the instruction that follows the CALL instruction (CS and EIP are stored on the stack) and then jumps to the called procedure. The called procedure executes. The last instruction in the called procedure should be a RET (Return). Execution of the RET instruction causes the processor to pop the previously-saved CS:EIP value off the stack, load it into CS:EIP, and fetch the instruction it points to. This is the instruction that follows the CALL instruction. Execution of the caller's program resumes at this point.

When calling a procedure that resides at a more privileged level through a Call Gate, some additional steps are necessary because of a potential, stack-related problem. If the called procedure uses the same stack (pointed to by SS:ESP, or SS:SP) as the caller, the stack may prove to be too small to hold additional values that the called procedure may push onto the stack. This would cause a Stack Overflow Exception. The processor addresses this problem by automatically switching to a new stack of sufficient size to hold CS:EIP (the address to return to in the calling program), SS:ESP (the pointer to the calling program's stack area) and any parameters that are passed by the caller (on the stack), as well as any local variables that the called procedure may subsequently need to push onto the stack.

When a procedure call (to a procedure on a more privileged level) is made through a Call Gate, the processor creates a new stack to receive the CS:EIP, SS:ESP and parameters from the caller. The Task State Segment (TSS) for the currently executing task is consulted by the processor to get the Stack Segment (SS) selector and ESP pointer for the new stack. Figure 8-11 on page 154 illustrates the format of the TSS. In the example, the call is to a level zero procedure, so the processor uses SS0 to supply the base address of the new stack and ESP0 to supply the pointer to the top of its stack. These are loaded into SS:ESP and the caller's CS:EIP, parameters (if any), and the caller's SS:ESP values are copied to the new stack.

Figure 8-11. Task State Segment Format


When calling a procedure (that resides at a more privileged level) through a Call Gate, the actions shown in Figure 8-12 on page 155 are performed in sequence.

Figure 8-12. Automatic Stack Switch When Procedure at Higher Privilege Level Is Called through Call Gate


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.149.213.209