• No results found

Interactions with the Underlying Hardware

4. Statically Checking Confidentiality of Low-Level Operating-System Code

4.2. Peculiarities of Low-Level Operating-System Code

4.2.2. Interactions with the Underlying Hardware

Device-register accesses, direct memory accesses (DMA), writes to special-purpose registers, modifications of hardware-traversed data structures, and the execution of privileged-mode in- structions cause a variety of effects that one would not expect from executing “normal” instruc- tions and memory accesses. Following Tews et al. [TVW09], I call these effects hardware side

effects.

Although second-generation microkernels implement device drivers outside the kernel, drivers for interrupt controllers, timers and IO protection units have to reside inside the micro- kernel. As a consequence, side effects due to device-register accesses and due to DMA are also triggered by the microkernel. For example on ARM processors [Ltd], DMA is used to copy data from main memory into on-chip scratch-pad memory and back.

The following is a classification of hardware side effects by the type of behavior they cause. There are:

• side effects, which cause undefined processor behavior, • critical side effects, and

• benign side effects.

Clearly, because undefined behavior may result in arbitrary leakages, programs that trigger side effects with such a behavior rule out any static information-flow analysis. Programs, which cause these side effects, must be rejected as potentially being insecure.

Side effects, which trigger a processor behavior that is sufficiently well defined in the pro- cessor manuals, fall into the last two classes. The determining criteria is thereby whether such a side effect rules out a further information-flow analysis. If so, the side effect is classified as a critical side effect and the side-effect triggering program must be rejected. Benign side effects may give rise to potentially harmful information flows. I call a side effect benign if a suitable static information-flow analysis can check whether these information flows violate the system’s security policy.

4.2.2.1. Side Effects causing Undefined Processor Behavior

In modern processor architectures, not all instruction combinations cause a behavior that is defined in the processor manuals. For example, the Intel 64 and IA32 Architectures Software Developer’s Manual specifies certain bits in the processor control registers [Cor09,§ 2.5 Vol. 3a] as reserved [Cor09, § 1.3.2 Vol. 3a]. Setting these bits to a different value may cause the processor to enter an unpredictable state.

Likewise, accesses to memory-mapped device registers can cause undefined behavior. For example, accessing the 32-bit registers of the local advanced programmable interrupt controller (APIC) of an IA32 processor with loads or stores that are not 128-bit aligned or accessing these registers with floating-point instructions can cause undefined behavior. As stated in [Cor09,

§ 9.4.1 Vol. 3a]: “This undefined behavior could include hangs, incorrect results or unexpected

exceptions, including machine checks, and may vary between implementations.”

Because we do not know which information a processor leaks if it behaves in an undefined way, we have to assume pessimistically that any information is leaked. Hence, programs that cause such an undefined processor behavior have to be rejected as potentially being insecure.

4.2.2.2. Critical Side Effects

The behavior of critical side effects is well defined. However, their occurrence impedes a static information-flow analysis of programs that cause these effects.

Examples of side effects with critical state changes include page-table changes that authorize user-level programs to modify kernel code or the stack on which this code executes. A setting of bit 1 and 2 in the corresponding page-table entries to user respectively to writable [Cor09,

§ 3.7ff Vol. 3a] enables this side effect. Control flows to user code while in kernel mode and

the disabling of paging followed by a return to user code are further side effects with critical state changes. The latter is triggered by resetting bit 31 in the IA32-CR0 register [Cor09,§ 2.5 Vol. 3a] or by executing the iret instruction on a stack frame, which refers to a kernel-code segment.

Once arbitrary user code can be injected into the kernel, adversaries can access any information the system stores. Consequently, programs that cause critical side effects must be rejected as potentially being insecure.

Our running example in Section 4.1modifies the variableregseaxon the kernel stack. This stack contains also the code-segment descriptor of the invoking user-level thread. Therefore, a precondition for accepting the example as secure is that the memory locations of the entry frame and of the variableregseaxare disjoint.

To verify the absence of critical side effects it is often helpful to observe that programs typi- cally modify special-purpose registers and hardware-traversed data structures only during their respective initialization phase. Assuming a correct setup, we can therefore verify the absence of critical side effects by showing that no writes happen to these critical locations.

One way to perform such an analysis is to mark the corresponding fields as unmodifiable and to reject programs that write to unmodifiable fields. For our running example, the entry frame, all page tables and other hardware-traversed data structures have to be marked as unmodifiable. When registers and hardware-traversed data structures are modified also after the initializa- tion phase, we have to rely on separately-established correctness results. An elaborate discus- sion how these properties can be established with the help of static analyses is out of the scope of this thesis.

4.2.2.3. Side Effects that cause Benign State Changes

If the processor manuals describe a hardware side effect sufficiently well to allow for an information-flow analysis of this side effect, I regard it as a benign side effect.

On IA32 processors, executing a read on a virtual addressv causes such a benign side effect.

If this read access was the first access to the page containing v, the processor will set the

accessed bits [Cor09,§ 3.7.6 Vol. 3a] in those page-table entries that are involved in the trans- lation ofv to the physical address p. If we assume that p is located in RAM, the read access of v does not modify the value at p. However, the fact of reading can be leaked to other programs

if these other programs are able to read the accessed bits from the used page-table entries. In the two L4-family microkernels L4-Pistachio [DLSU04] and Fiasco [Hoh02], the system call

L4-unmapreturns the accumulated accessed and dirty bits of all direct and indirect recipients of an unmapped memory page. In these systems, the setting of accessed bits constitutes an implicit information flow. The flow is implicit because only the access but not the accessed data is revealed. An immediate consequence of this information flow is that multi-level servers must not access client-provided memory in a secret context, that is, in a context with a secrecy level lip to which the respective clients τ are not cleared (lip  dom(τ)). We shall return to

this example in greater detail in Section 4.3 and in the case study in Section 5.1. The IA32 processor manuals describe the processor behavior on virtual memory accesses sufficiently well to allow for a formalization of the above hardware side effects and for an analysis of the information flows it involves.

Further examples of benign hardware side effects include legitimate modifications of memory- mapped device registers, the modification of the kernel stack in situations where interrupts or exceptions cause a kernel entry, and DMA transfers to memory regions that the DMA initiating driver can legitimately access2.

There are three principle approaches to cope with benign hardware-side effects:

• the benign side effect and its contained information flows can be formalized and subjected

to the same information-flow analysis as the side-effect triggering code;

• the program, which triggers such a benign side effect, can be rejected as potentially being

insecure; or

• to checked program (respectively the kernel) can be modified to not reveal the information

a benign side effect propagates.

This work advocates the first approach by formalizing hardware side effects as interleaved- executing Toy programs, which are checked together with the translated C++ operating-system code. However, sometimes it is also feasible to follow the last two approaches. For instance, IA32 processors support a wide range of hardware features that modern microkernels don’t use. Examples include hardware task switches [Cor09, § 7.3 Vol. 3a] and real-mode kernel code [Cor09, § 17.1 Vol. 3a]. A sound analysis, which shows that the kernel does not invoke these features, relieves us from formalizing this rather complex behavior. For accessed bit propagation, the two alternatives translate into:

1. rejecting programs that set accessed bits, and 2. modifying the kernel to not return these bits. However, both alternatives have severe drawbacks:

1. All virtual memory accesses set accessed bits, which means we would have to reject any program that accesses memory in a secret context; and

2. Without accessed-bit information, page-replacement algorithms would have to emu- late these bits. However, this emulation comes at a significant performance degrada- tion [Dra91].

To deal with programs that initiate DMA requests, I propose to treat DMA-accessible memory as “normal” shared memory. There are however three important points to notice:

1. DMA memory remains accessible even if no driver thread runs;

2. DMA does not adhere to locking schemes unless the driver holds a respective lock until the DMA transfer completes; and

3. DMA can access memory even if this memory is not accessible in the address space of the driver.

Related documents