1 / 44

Software fault isolation with API integrity and multi-principal modules

Software fault isolation with API integrity and multi-principal modules Yandong Mao, Haogang Chen ( MIT CSAIL ), Dong Zhou ( Tsinghua University IIIS ), Xi Wang, Nickolai Zeldovich , Frans Kaashoek ( MIT CSAIL ). Kernel security is important. Kernel is fully privileged

Download Presentation

Software fault isolation with API integrity and multi-principal modules

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Software fault isolation with API integrity and multi-principal modules Yandong Mao, Haogang Chen (MIT CSAIL), Dong Zhou (TsinghuaUniversity IIIS), Xi Wang, NickolaiZeldovich, FransKaashoek (MIT CSAIL)

  2. Kernel security is important • Kernel is fully privileged • Kernel compromises are devastating • Remote attacker takes control over the whole machine • Local user gains root privilege

  3. Linux kernel is vulnerable • Vulnerabilities in Linux are routinely discovered • CVE 2010: 145 vulnerabilities in Linux kernel • Many exploits attack kernel modules • 67% of Linux kernel vulnerabilities (CVE 2010) • This talk focuses on vulnerabilities in kernel modules

  4. Threat • Module programmer makes mistake • Attacker exploits mistake to mount attacks • Example: buffer overflow, set current UID to root Module Privilege escalation! Kernel memory Module memory UID

  5. One approach: type safe languages • Write kernel and modules in Java, C# • No reference to UID object => cannot directly change UID • Attacker cannot synthesize references Module Most kernels are not written in type safe language! UID

  6. Software Fault Isolation (SFI[SOSP93]) Module Can not bypass SFI check char *p = 0xf7; sfi_check_memory(p); *p = 0; SFI Runtime void sfi_check_memory(p) { if p not in “Module memory” stop_module(); } Module memory UID

  7. Memory safety is insufficient for stopping attacks! • Challenge: module needs to call kernel functions Core Kernel Spin_module • void spin_lock_init(spinlock_t*lock) { lock->v = 0; } spinlock_tmylock; spin_lock_init(&mylock); Module memory UID

  8. Problem: API abuse • Attacker tricks fully-privileged kernel code to overwrite UID Core Kernel Spin_module • void spin_lock_init(spinlock_t*lock) { lock->v = 0; } spin_lock_init(&cur_proc->uid); Privilege escalation! Module memory UID

  9. Challenge: lack of API integrity • Kernel APIs are not written defensively • Assume the calling module to obey implicit rules • Do not check arguments, permissions, etc • Problem: modules cannot be trusted to follow rules • Module can trick kernel into performing unexpected actions • Ideal system would enforce rules for kernel API • Analogy: system call code assumes nothing about caller, checks every assumption

  10. State of the art for protecting APIs • SFI[SOSP93]: memory safety • XFI[OSDI06]: no argument checks • BGI[SOSP09]: manually wrap functions, make kernel defensive when kernel code invokes callbacks • Error-prone and time-consuming • Works if kernel code is well-structured (not Linux)

  11. Our approach: annotation language • Helps enforce two types of API integrity: • Argument integrity: programmer controls what arguments a module can pass to functions • Callback integrity: kernel invokes callback only if the module could have invoked callback directly • Allows programmers to specify principals for privilege separation within a module • Less error-prone than manual wrapping, applicable to complex APIs such as those in Linux

  12. Contributions • LXFI: software fault isolation system for Linux kernel modules • Annotation language for • Argument integrity • Callback integrity • Privilege separation within a module • Evaluation • Few annotations for 10 Linux kernel modules • Stop three real exploits • 2-4X CPU overhead for netperf

  13. Goals for annotation language • Enforce argument integrity, callback integrity and privilege separation within a module • Minimize programmer effort, e.g.: • Few annotations • Avoid data structure and API changes • Compatible with C

  14. Preventing module exploits Programmer annotates core kernel If annotations capture all implicit rules, compromised module cannot violate rules to gain additional privileges. Using compiler plugins; Provide safe default: reject a module if it calls an unannotated API LXFI translatesannotationsto runtime checks Compile time Consulting a dynamic table of capabilities for each module LXFI performs checks Runtime

  15. Design of annotation language • Argument integrity annotations • Using the spin_lock_initexample • Callback integrity annotations • Not discussed; see paper • Privilege separation annotations • Using dm_crypt(real Linux kernel module)

  16. Enforce argument integrity • spin_lock_init: three annotations are required

  17. Example: enforce argument integrity for spin_lock_init Core Kernel Spin_module void spin_lock_init(spinlock_t*lock) pre(check(write(lock, sizeof(spinlock_t))) capability table write(mylock, 8) LXFI Runtime • lxfi_check_write(mylock, 8); spin_lock_init(mylock) …… • lxfi_check_write(&cur_proc->uid, 8); spin_lock_init(&cur_proc->uid) …… Privilege escalation prevented Module memory UID

  18. Where does the capability come from? • Granted on allocation • Two more annotations are required

  19. Example: grant spinlock Core Kernel Spin_module void *kmalloc(size) post(copy(write(return, size)) spinlock_t *mylock = kmalloc(8); lxfi_copy_write(mylock, 8); …… LXFI Runtime capability table write(mylock, 8)

  20. What happens when memory is freed? • Need to revoke capability to safely reuse memory • Strawman: revoke capability from caller • Insufficient! Other modules may have copies of capability No other copies of the capability remain

  21. Example: safely free a spinlock Core Kernel Spin_module void kfree(void *p) pre(transfer(write(p, no_size))) LXFI Runtime • lxfi_transfer_write(mylock, -1); kfree(mylock); …… capability table write(mylock, 8) other_module capability table write(mylock, 8)

  22. Why is spin_module able to call spin_lock_init, kmalloc, kfree? • Call capability • Granted initially according to the module’s symbol table • Trust module author not to call unnecessary functions • Dynamically granted when a callback function is passed

  23. Core Kernel Spin_module void *kmalloc(size) post(copy(write(return, size)) void spin_lock_init(spinlock_t *lock) pre(check(write(lock, sizeof(spinlock_t))) void kfree(void *p) pre(transfer(write(p, no_size)) capability table call(kmalloc) call(spin_lock_init) call(kfree) LXFI Runtime …… spinlock_t *mylock = kmalloc(8); lxfi_copy_write(mylock, 8); lxfi_check_write(mylock, 8); spin_lock_init(mylock)l lxfi_check_write(&cur_proc->uid, 8); spin_lock_init(&cur_proc->uid); lxfi_transfer_write(mylock, -1); kfree(mylock); …… …… ……

  24. No way for compromised spin_module to gain root privilege • SFI ensures memory safety • Call capabilities ensure only 3 functions are allowed • None of the functions can modify UID because: • kmalloc never modifies allocated memory • spin_lock_init can only be called with writable memory (from kmalloc) • kfree ensures no capabilities remain after free • spin_module can not modify UID!

  25. Privilege separation within a module • dm_crypt: transparent encryption service for block devices • This example requires a third type of capability Pass argument a as type t

  26. Privilege separation write(“/etc/secret.txt”, “foo”) User space Kernel space Core Kernel intbdev_write(block_device *dev, const char * data, …) pre(check(ref(block_device), dev) write(enc_disk, “foo”, …) dm_crypt capability table ref(block_device, enc_disk->bdev) Writing block device does not require writing to memory of enc_disk->bdev. LXFI Runtime • lxfi_check_ref(block_device, enc_disk->bdev) bdev_write(enc_disk->bdev, E(“foo”), …)

  27. Privilege separation read(…) User space Kernel space Core Kernel intbdev_write(block_device *dev, const char * data, …) pre(check(ref(block_device), dev) dm_crypt capability table ref(block_device, enc_disk->bdev) ref(block_device, enc_usb->bdev) capability table ref(block_device, enc_disk->bdev) capability table ref(block_device, enc_usb->bdev) LXFI Runtime Decrypt • lxfi_check_ref(block_device, enc_disk->bdev) bdev_write(enc_disk->bdev, “/etc/pwd”, “foo”) /etc/pwd: rootpwd=foo

  28. How to define principals • Associate a principal with every instance a module supports (e.g. block device in dm_crypt) • Problem: how to specify and name principals? • Recall goal: minimize changes to existing data structures • Idea: re-use address of data structure as the name of the principal • Can typically identify principal from one of the function arguments

  29. Specifying principals

  30. Privilege separation User space Kernel space Core Kernel structdm_type { int (*map)(structdm_target *di); principal(di)}; lxfi_set_princ(enc_usb) dm_crypt.map(enc_usb) dm_crypt capability table write(enc_disk->bdev, 100) capability table write(enc_usb->bdev, 100) LXFI Runtime Decrypt • lxfi_check_write(enc_disk->bdev, 100) bdev_write(enc_disk->bdev, “/etc/pwd”, “foo”) /etc/pwd: rootpwd=foo

  31. Principal name aliasing • Problem: Kernel identifies a LXFI principal by multiple addresses • Insert code into module to create alias • The same principal now has multiple names inte1000_probe(structpci_dev *pcidev) { structnet_device *ndev= alloc_etherdev(...); ndev->pcidev = pcidev; ... } int e1000_xmit(structnet_device *dev) { …} lxfi_princ_alias(pcidev, ndev);

  32. Other annotation language features Save annotation effort for complex objects that need multiple capabilities Express conditional action such as grant a privilege if return value is OK Global:principal with full privilige Shared:principal with minimal privilege

  33. Implementation • Linux 2.6.36, x64, single-core • gccplugin: kernel rewriting for callback integrity • Clang/LLVMplugin: module rewriting • Annotation propagation saves effort by inferring annotations of module functions

  34. Example: annotation propagation //linux/drivers/net/e1000/e1000_main.c int e1000_probe(structpci_dev *pcidev) { ….} structpci_driver e1000_driver = { .probe = e1000_probe }; //from linux/include/pci_driver.h structpci_driver { int (*probe)(structpci_dev *pcidev) principal(pcidev) pre(copy(ref(structpci_dev), pcidev) } //linux/drivers/net/ixgbe/ixgbe_main.c intixgbe_probe(structpci_dev *pcidev) { ….} structpci_driverixgbe_driver = { .probe = ixgbe_probe }; LXFI propagates annotation on probe to modules

  35. Evaluation • Security • Annotation effort • Performance overhead

  36. Security • Test LXFI with three real privilege escalation exploits • Stopping real attacks requires API integrity

  37. Annotation effort • Annotate kernel APIs for 10 modules, one at a time • Count: • # of annotated core kernel functions a module calls • # of function pointer declarations a module exports to core kernel

  38. Sharing reduces annotation effort

  39. LXFI performance • netperf, 1 Gigabit e1000 network card, LAN • Stresses LXFI ~30% decrease

  40. CPU time of LXFI actions for netperf • Room for improvement 80%

  41. Future work • Improve performance • Faster capability management such as BGI’s • Extend annotation language to enforce other types of API integrity • Perhaps based on Singularity’s contracts

  42. Related work • Type-safe kernels: Singularity [MSR-TR05] • LXFI provides similar guarantees in C • Good support for revocation (transfer) and principals • Software fault isolation • LXFI extends existing SFI systems (SFI, XFI, BGI) with annotation language

  43. Conclusion • Extend SFI with annotation language for: • Argument integrity • Callback integrity • Principals • LXFI: Prototype for Linux • Annotated 10 kernel modules • Prevented 3 real privilege escalation exploits • 2-4X CPU overhead when stressing with netperf

  44. Q & A

More Related