Lab 3 tutorial Instructor: Youngjin Kwon 1
Lab 1 Lab 2 Initialize page metadata (struct PageInfo) array kern/bootstrap.S Implement simple physical kern/entry.S memory allocator Kern/init.c Setup kernel virtual memory x64_vm_init() - Page table walk/manipulation Key function: boot_map_region() Kernel Image 2
To support user-level processes • Constructing process abstraction • System calls • Interrupts handling and return from interrupts • User-level memory support • User-level memory layout • Page fault handling from the user-level memory • Scheduling & Context switch (multi-processes) 3
About Lab 3 • Part A • Building framework for user environments (a.k.a. processes) • Handling interrupts • Part B • Handling page faults & exceptions • Implementing system calls and kernel memory protection 4
Design thinking: control transfer between kernel and user • Let’s say OS wants to do the control transfer • E.g., system calls, interrupts, disk IO etc • User kernel: OS stores processor states to a certain location • Kernel user: OS restores the machine states from the location • What is the processor states? • Where is the location (revisit later)? 5
Representing processor states CPU registers Page table (root pointer) 6
Process abstraction 7
How to launch a process? • Create a new process ( env_create ) • Allocate a new environment ( env_alloc ) • Setup initial page table ( env_setup_vm ) • Load a program binary ( load_icode ) • Execute the process ( env_run ) 9
Load a program binary • -b binary: Treat .o file as binary file • KERN_BINFILES will be stored with ELF format along with kernel image) • Load_icode (you should fill) • Parse the program (formatted as elf binary) • Load code section to memory; look at comments in code • Set an initial entry point of the program • Set user-level stack • Setup debugging information (refer to find_debug_sections ()) 10
Execute a process: jump from kernel to user process • env_run (you should fill) • Set env state: current running env and the new env • Switching address space (load new cr3 value) • Loading processor states, struct Trapframe ( env_pop_tf ) Do you know what does the code mean? 11
How to jump from kernel to user-level? • X86 does not allow direct jump from kernel to user-level • Kernel must use iret instruction • X86 CPU has a protocol when executing iret • Before executing iret, CPU expects a specific stack frame, called exception parameter When iret is executed, low address RSP The instruction to continue execute RIP The code segment selector to change to CS The value eflags register to load EFLAGS RSP The stack pointer to load SS The stack segment selector to change to high address 12
Low address RSP pointers after the instruction is executed Exception parameter Low address RIP CS EFLAGS RSP High address SS High address 13
Key code flow to implement • env_create • env_alloc – env_setup_vm • load_icode – region_alloc • env_run 14
Interrupt • A event altering the sequence of instructions executed by processer • A electrical signal generated by hardware circuit both inside and outside CPU • Asynchronous interrupt (interrupt) • Generated by hardware at arbitrary time Interrupt or exception? • e.g., IO signal Page fault System call • Synchronous interrupt (exception) timer • Produced by CPU while executing instructions Control + C General protection error • e.g., divided by zero • Trap : software-generated exception 15
Interrupt as protected control transfer • On interrupt, a user process running in a CPU stops • CPU transfers control from user to kernel • Who does decide the target address of the control transfer? • What if a user-process decide the address? • E.g., key-board interrupt -> a kernel function that set uid to 0 • Kernel carefully decides the target address • Hardware performs the control transfer with the information 16
Interrupt and IRQ Interrupt ReQuest (IRQ): Each hardware has a single output line connected to IRQ line All IRQ lines are connected to hardware circuit called Programmable Interrupt Controller (PIC) • Each hardware assigned an IRQ number (0 to 255) • Check ‘cat / proc /interrupts’ • Also called interrupt number , interrupt vector (or exception vector ) 17
Interrupt descriptor table (IDT) • Entry points of kernel when interrupt or exception happens • A table indexed by interrupt vector Each IDT entry looks like this: CPU sets RIP to offset(16-31)||offset(0-15) to transfer control 18
Interrupt: What happens in user-level? • Control is transferred to kernel Kernel User: OS stores processor states to a certain location User Kernel: OS restores the machine states from the location • The certain location: Task State Segment (TSS) Low address • Control transfer (to kernel) steps RIP • CPU stores current registers, RIP, and RSP to TSS CS • CPU loads “Kernel stack pointer“ in TSS EFLAGS • CPU sets “ interrupt parameters ” to the kernel stack RSP • CPU jumps to the entry point specified by IDT SS High address 19
Example: divided by zero • CPU switches to kernel stack from TSS (SS0 and RSP0 field) • CPU pushes the exception parameters onto the kernel stack • CPU reads IDT entry 0 (divided by zero) and set RIP from IDT • The RIP is the address of handler function of divided by zero • Kernel takes the control and performs a proper action • E.g., terminating the user environment 20
Call flow for interrupt handling • i386_init() • trap_init() : setup IDT; check trapname () function for # of traps to support • trap_init_percpu() : Setup TSS and load IDT [interrupt happens] • IDT (trapentry.S) • _alltraps : common routine to setup register and stack frame to call a kernel function, trap() • trap() : takes the parameter of struct trapframe, set by _alltraps • Trap_dispatch(): do actions for corresponding traps 21
About lab 3 • Part A • Building framework for user environments (a.k.a. processes) • Handling interrupts • Part B • Handling page faults & exceptions • Implementing system calls and kernel memory protection 22
Handling page fault • T_PGFLT: exception vector 14 • CR2: linear address causing the page fault • Page fault handling path • IDT Trap () • Trap_dispatch () • page_fault_handler () • Panic in kernel page fault • Print trapframe and destroy user environment in user page fault 23
Implementing system calls (user part) • System call interrupt: int $0x30 • Interrupt vector 48 (0x30) • System call x84_64 ABI 24
Implementing system calls (kernel part) • trap_dispatch () • syscall () (kern/syscall.c): execute handlers for each system call 25
User-mode setup • The environment array, envs, is exposed to user level with read-only • Control flow of a user program (e.g., user/hello.c) • lib/entry.S • libmain (): setup thisenv (currently running environment) from sys_getenvid syscall • umain (): body of a user program 26
Syscall: memory protection in action • By syscall, a user program and kernel communicate • E.g., sys_cputs Pointer from a user process • What are problems? • If s is not mapped in user level, kernel would experience PF • PF in kernel address typically bug (e.g., NULL pointer reference in kernel code) • PF in user address Kernel maps the user page in PF handler • How to distinguish the two case? • What if s contains kernel address space? • E.g., malicious user processes try to print contents of kernel memory 27
Buggy/malicous code examples user/buggyhello.c user/evilhello.c user/buggyhello2.c 28
Sanity check in system call handler • Implement user_mem_check() called in system call handler • Check all pointer passed from user-level into kernel 1. The pointer address belongs to user-level 2. Page table of the pointer address has a right permission to allow the operation Now you can defeat buggyhello and evilhello! 29
Recommend
More recommend