dusk - develop at userland install into kernel

35
DUSK: Develop at User level, inStall in Kernel Alexey Smirnov and Tzi-cker Chiueh ECSL Research Seminar 09/13/05

Upload: alexey-smirnov

Post on 06-May-2015

3.816 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: DUSK - Develop at Userland Install into Kernel

DUSK: Develop at User level, inStall in Kernel

Alexey Smirnov and Tzi-cker ChiuehECSL Research Seminar

09/13/05

Page 2: DUSK - Develop at Userland Install into Kernel

Outline

• Introduction• Related Work• Netfilter Overview• System Architecture• Evaluation• Conclusion

Page 3: DUSK - Develop at Userland Install into Kernel

Introduction

• Kernel is often extended using kernel modules.

• Netfilter – hooks in network component.• Development at user-level is

convenient: gdb, ddd, etc.• Kernel modules have lower overhead.• DUSK achieves best of both worlds.

Page 4: DUSK - Develop at Userland Install into Kernel

User-level Development of Kernel Extensions

• Provide kernel API at user-level. A lot of functions, changes from one version to another.

• Implement a new API that resembles kernel API. Not convenient for the programmer, requires code rewriting.

Page 5: DUSK - Develop at Userland Install into Kernel

DUSK Overview

• DUSK is an extension to GCC that compiles the source code of a kernel module into a user-level program.

• It links several helper functions to the user-level module.

• Same helper functions for different versions of Linux kernel.

Page 6: DUSK - Develop at Userland Install into Kernel

DUSK Framework

• User-level component: the kernel module compiled as a user level program.

• Kernel-level component: handles user-level module’s requests.

• The two components are connected using UDP sockets.

• Can run on different architectures: user-level module on x86 running in gdb and kernel-level module on MIPS wireless router.

Page 7: DUSK - Develop at Userland Install into Kernel

Related Work

• VFS layer: UFS uses NFS loopback API. UpcallFS – a stackable file system.

• Device drivers: Userdev provides a user-level library.

• Network stack: icTCP exposes TCP stack parameters to user programs. Netfilter simulator runs Netfilter hooks at user level.

Page 8: DUSK - Develop at Userland Install into Kernel

Netfilter Architecture• Netfilter adds a set of five hooks to

kernel network stack:

• A Netfilter module verdict: NF_ACCEPT, NF_DROP, NF_STOLEN, NF_QUEUE, NF_REPEAT.

Page 9: DUSK - Develop at Userland Install into Kernel

Netfilter User Mode Modules• NF_QUEUE verdict sends sk_buff to

user space using a netlink socket. The queue handler is either standard or programmer-defined.

• A user module can only read sk_buff but cannot change kernel memory.

Page 10: DUSK - Develop at Userland Install into Kernel

iptables

• iptables controls parameters of Linux firewall.

• iptables -A PREROUTING –p tcp --destination-port 80 –j QUEUE

• iptables –A POSTROUTING –p udp --source-port 5678 –j DROP

• Has string matching capabilities. Stateless IDS.

Page 11: DUSK - Develop at Userland Install into Kernel

Kernel-level Programming at User Level

• User-level kernel modules need to:• Read/write kernel memory;• Call kernel functions;• Access global kernel variables, e. g.

current• Programmers can modify source

code of kernel module using these blocks to run it at user level.

Page 12: DUSK - Develop at Userland Install into Kernel

Three Basic Blocks

• Kernel memory access: /dev/kmem• Kernel function calls: new system call

sys_exec(). System.map for address lookup.

• A new system call sys_kvar() for variable access.

• sys_exec() and sys_kvar() are implemented in DUSK kernel module.

• Kernel module and user module communicate using UDP sockets.

Page 13: DUSK - Develop at Userland Install into Kernel

Using Basic Blocks to Run Kernel Module at User Level

• Kernel module source code:sk_buff->len• User-level code:

• Define a shadow variable u_sk_buff;• malloc() memory for it;• Use kmem_read() to copy sk_buff from kernel

memory to shadow variable;• Commit changes to u_sk_buff using

kmem_write().

• Our goal: automatic transformation.

Page 14: DUSK - Develop at Userland Install into Kernel

DUSK Framework

Page 15: DUSK - Develop at Userland Install into Kernel

DUSK Run-Time Support

• Kernel extension registration/de-registration. The address of a function is sent to the kernel.

• Processing kernel requests. An appropriate extension handles each request.

• Module initialization/cleanup. init_module() and cleanup_module() are called when user-level module starts and terminates.

Page 16: DUSK - Develop at Userland Install into Kernel

Extension Management

nfho_post_routing.hook=khook_ip_input;nfho_post_routing.hooknum = NF_IP_POST_ROUTING;

nf_register_hook(&nfho_post_routing);

• Kernel-level DUSK module replaces khook_ip_input with a proxy kernel function and returns extension type and sequence number to the user program.

• DUSK clones a new process for each extension. They share same address space.

Page 17: DUSK - Develop at Userland Install into Kernel

Blocking and Non-blocking Extensions• Extensions that block: the process

that called the extension blocks until the user-level module returns a verdict. Exampe: procfs, timer.

• Extensions that don’t block: the kernel callback returns as soon as a message is sent to the user space. Example: Netfilter.

Page 18: DUSK - Develop at Userland Install into Kernel

Why Netfilter Is Non-blocking?• Hardware interrupt handler receives

network packets.• Runs with interrupts disabled. It saves

packets in a queue and invokes software interrupt, then returns.

• One software interrupt handler per processor. Hardware interrupts enabled.

• A packet is re-injected into the network stack when user-level processing is finished.

Page 19: DUSK - Develop at Userland Install into Kernel

Extension Types

• DUSK supports Netfilter only.

• Timers, threads, procfs, ioctl, etc. are required for advanced modules.

Page 20: DUSK - Develop at Userland Install into Kernel

DUSK Run-Time Configuration

Page 21: DUSK - Develop at Userland Install into Kernel

Compile-time Support

• DUSK adds two functions: check() and commit().

• check() ensures that every buffer accessed using a pointer exists in kernel memory and in user-space.

• commit() updates the kernel version when a function is called; it refreshes the user version when the function returns.

Page 22: DUSK - Develop at Userland Install into Kernel

Function check()

• check() is called for every array access, de-referenced pointer, or &.

• It maintains the kernel-to-user address mapping buffer.

• For a new user address DUSK calls kmalloc() and kmem_write()

• For a new kernel address DUSK calls malloc() and kmem_read().

• Addresses under PAGE_OFFSET are user addresses, above are kernel addresses.

Page 23: DUSK - Develop at Userland Install into Kernel

Type Information

• Type information is gathered at compile-time. Type size, offsets of pointer fields are stored.

• Type size is used in check(). • commit() uses field information.

Page 24: DUSK - Develop at Userland Install into Kernel

Kernel Function Calls

• A kernel function is replaced with:• void_kernel_func() for void functions;• int_kernel_func() for int functions;

• Function arguments are written into kernel memory when the function is called.

• Each pointer-type argument is wrapped into commit() call.

Page 25: DUSK - Develop at Userland Install into Kernel

Function commit()

• commit() traverses data types recursively.

• Issue: array elements accessed using a pointer: *(a+1), *(a+2). If a is a function parameter then commit() ensures that all elements get synchronized.

• Issue: a union’s elements of different type have same offset. Types of the argument and that of the address mapping table are compared.

Page 26: DUSK - Develop at Userland Install into Kernel

Function commit()

Page 27: DUSK - Develop at Userland Install into Kernel

Function Prolog and Epilog

• All changes are committed when user-level module returns a verdict.

• DUSK adds a function epilog that commits the changes.

• depth variable counts the current nesting level.

• Incremented in the function prolog, decremented in the epilog.

Page 28: DUSK - Develop at Userland Install into Kernel

check() and commit() Example• printk(“test”);• int_kernel_func(addr_of(“printk”), commit(check(“test”)));

Page 29: DUSK - Develop at Userland Install into Kernel

Cross-Platform Debugging

• Linksys WRT54gs wireless router: 32 MB RAM, 200 MHz MIPS CPU. Runs Linux 2.4.20.

• Cannot run gcc, gdb. Supports Netfilter.

• printk() debugging possible. Logs are not stored after reboot.

Page 30: DUSK - Develop at Userland Install into Kernel

X86 and MIPS Differences

• Data structures are different:

• PAGE_OFFSETs are different.• DUSK compiles module twice: with the cross-

compiler and with x86 compiler.• Addresses in data structures are changed when

data from kernel is received.

Page 31: DUSK - Develop at Userland Install into Kernel

Evaluation

• nfsiff – FTP password sniffer• POSTROUTING: finds USER and PASS

commands;• PREROUTING: replies to special ICMP packets;

• lwfw – light-weight firewall• PREROUTING: drops certain packets (port,

interface).

• ipp2p – P2P traffic classifier• POSTROUTING: scans for P2P signatures.

Page 32: DUSK - Develop at Userland Install into Kernel

nfsiff

• Sniffer on wireless router:

Page 33: DUSK - Develop at Userland Install into Kernel

Compile-time Overhead

Page 34: DUSK - Develop at Userland Install into Kernel

Saved Work

Page 35: DUSK - Develop at Userland Install into Kernel

Conclusion

• DUSK allows to debug kernel modules at user level without changing the source code.

• Future work: add better debugger support, i.e. integrate DUSK with gdb and ddd.

• Support device driver development.