├── .gitignore ├── Makefile ├── README ├── apps ├── Makefile ├── sandbox │ ├── Makefile │ ├── boxer.h │ ├── exec.c │ ├── main.c │ ├── nullsandbox.c │ ├── sandbox.h │ ├── sandbox.ld │ ├── sandbox_wrap.sh │ ├── trap.c │ └── umm.c ├── ufirewall │ ├── Makefile │ ├── firewall.c │ ├── firewall.h │ ├── firewall_test.c │ └── ufw.rules └── wedge │ ├── Makefile │ ├── bench.c │ ├── httpd.c │ ├── index.html │ ├── sthread.c │ ├── sthread.h │ ├── test.c │ └── wedge_bench.sh ├── bench ├── Makefile ├── bench.h ├── bench_dune.c ├── bench_dune_ring.c └── bench_linux.c ├── build-eglibc.sh ├── dune_env.sh ├── dune_req.sh ├── eglibc-2.14.diff ├── kern ├── Makefile ├── compat.h ├── core.c ├── dune.h ├── ept.c ├── extract_symbol.sh ├── preempttrap.c ├── preempttrap.h ├── vmx.c └── vmx.h ├── libdune ├── Makefile ├── cpu-x86.h ├── debug.c ├── debug.h ├── dune.S ├── dune.h ├── elf.c ├── elf.h ├── entry.c ├── fpu.h ├── local.h ├── mmu-x86.h ├── mmu.h ├── page.c ├── procmap.c ├── trap.c ├── types.h ├── util.c ├── vm.c └── vsyscall.S └── test ├── Makefile ├── hello.c ├── hugepages.c ├── hugepages.h ├── hugepages_mod.c ├── test.c ├── test_sandbox.c └── timetest.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | *.a 4 | *.swp 5 | *.hi 6 | *.cmd 7 | *.out 8 | dist 9 | apps/sandbox/sandbox 10 | apps/ufirewall/ufirewall 11 | apps/ufirewall/firewall_test 12 | apps/wedge/bench 13 | apps/wedge/httpd 14 | apps/wedge/test 15 | bench/bench_dune 16 | bench/bench_dune_ring 17 | bench/bench_linux 18 | eglibc-2.14/ 19 | kern/Module.symvers 20 | kern/dune.ko 21 | kern/dune.mod.c 22 | kern/modules.order 23 | kern/tmp/ 24 | test/hello 25 | test/test 26 | test/test_sandbox 27 | test/timetest 28 | tags 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LIBC = eglibc-2.14/eglibc-build/libc.so 2 | SUBDIRS = kern libdune 3 | 4 | all: $(SUBDIRS) 5 | libc: $(LIBC) 6 | 7 | $(SUBDIRS): 8 | $(MAKE) -C $(@) 9 | 10 | $(LIBC): 11 | sh build-eglibc.sh 12 | 13 | clean: 14 | for dir in $(SUBDIRS); do \ 15 | $(MAKE) -C $$dir $(@); \ 16 | done 17 | 18 | distclean: clean 19 | rm -fr eglibc-2.14 20 | 21 | .PHONY: $(SUBDIRS) clean distclean 22 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Overview 2 | ======== 3 | 4 | Dune is a system that lets you safely run applications in Ring 0 by using 5 | hardware virtualization. This lets applications access privileged CPU features 6 | and do things like change their own page table, register interrupt handlers and 7 | more, while still being able to perform normal system calls. More information 8 | is available here: 9 | 10 | http://dune.scs.stanford.edu/ 11 | 12 | Dune has two components: 13 | 14 | 1. A kernel module to enable virtualization (kern) 15 | 2. A utility library to help with using Dune (libdune) 16 | 17 | We also provide an optional patched glibc (eglibc-2.14). It slightly 18 | improves system call performance by performing a VMCALL directly. 19 | If used, it does not need to be installed globally. 20 | 21 | Dune is enabled only on applications that call dune_init(). All other 22 | applications on the system remain unaffected. 23 | 24 | The directory layout of this archive is as follows: 25 | kern/ -> the Dune kernel module 26 | libdune/ -> the Dune library OS 27 | bench/ -> a series of benchmarks to compare Dune and Linux performance 28 | test/ -> simple test programs and examples 29 | sandbox/ -> a generic implementation for sandboxing untrusted binaries 30 | 31 | Requirements 32 | ============ 33 | 34 | * A 64-bit x86 Linux environment 35 | * A recent Intel CPU (we use Nehalem and later) with VT-x support. 36 | * A recent kernel version --- We use 3.0 and later, but earlier versions 37 | may also work. 38 | * Kernel headers must be installed for the running kernel. 39 | 40 | We provide a script called dune_req.sh that will attempt to verify 41 | if these requirements are met. 42 | 43 | Setup 44 | ===== 45 | 46 | # make 47 | # insmod kern/dune.ko 48 | # test/hello 49 | 50 | You'll need to be root to load the module. However, applications can use 51 | Dune without running as root; simply change the permission of '/dev/dune' 52 | accordingly. 53 | 54 | Another program worth trying after Dune is setup is the Dune benchmark suite. 55 | It can be run with the following command: 56 | 57 | # bench/bench_dune 58 | 59 | Run the following command to build a faster version of glibc (optional): 60 | 61 | # make libc 62 | 63 | If eglibc build fails some systems (e.g. Ubuntu) may have incompatible default 64 | CFLAGS set. Before running the libc build set the following flags. 65 | 66 | # setenv CFLAGS "-U_FORTIFY_SOURCE -O2 -fno-stack-protector" 67 | 68 | The alternate glibc can be used by prefixing dune apps with the 69 | dune_env.sh script. 70 | 71 | Limitations 72 | =========== 73 | 74 | Dune is fairly far along, but could benefit from better support for signals 75 | and more robust pthread support inside libdune. We're currently working on 76 | these issues. 77 | 78 | Programming 79 | =========== 80 | 81 | 1. Call dune_init() to enter dune mode. (Link to libdune.) 82 | 2. The application will continue to function as normal. You can use printf, 83 | use sockets, access files, etc. 84 | 3. But you can then also perform privileged CPU instructions. 85 | 86 | Questions? 87 | ========== 88 | 89 | Contact us at dune@scs.stanford.edu. 90 | 91 | Last edited: 10/05/12 92 | 93 | -------------------------------------------------------------------------------- /apps/Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = sandbox wedge ufirewall 2 | 3 | all: $(SUBDIRS) 4 | 5 | $(SUBDIRS): 6 | $(MAKE) -C $(@) 7 | 8 | clean: 9 | for dir in $(SUBDIRS); do \ 10 | $(MAKE) -C $$dir $(@); \ 11 | done 12 | 13 | .PHONY: $(SUBDIRS) clean 14 | -------------------------------------------------------------------------------- /apps/sandbox/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | LD = ld 3 | RANLIB = ranlib 4 | CFLAGS = -Wall -O2 -MD -I ../../ 5 | LDFLAGS = -O2 -L. -L ../../libdune -lsandbox -ldune -lpthread -T sandbox.ld 6 | OBJ = main.o umm.o trap.o exec.o 7 | 8 | all: libsandbox.a sandbox 9 | 10 | libsandbox.a: $(OBJ) 11 | $(AR) cru $(@) $(OBJ) 12 | $(RANLIB) $(@) 13 | 14 | sandbox: nullsandbox.o libsandbox.a ../../libdune/libdune.a 15 | $(CC) -o $(@) $(<) $(LDFLAGS) 16 | 17 | clean: 18 | rm -f *.o test *.d sandbox libsandbox.a 19 | 20 | -include *.d 21 | -------------------------------------------------------------------------------- /apps/sandbox/boxer.h: -------------------------------------------------------------------------------- 1 | #ifndef __BOXER_H__ 2 | #define __BOXER_H__ 3 | 4 | typedef int (*boxer_syscall_cb)(struct dune_tf *tf); 5 | 6 | extern void boxer_register_syscall_monitor(boxer_syscall_cb cb); 7 | extern int boxer_main(int argc, char *argv[]); 8 | 9 | #endif /* __BOXER_H__ */ 10 | -------------------------------------------------------------------------------- /apps/sandbox/exec.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define EXECPGSIZE 4096 13 | 14 | extern char **environ; 15 | const char *sandbox_path = "./sandbox"; 16 | const char *ld_path = "/lib64/ld-linux-x86-64.so.2"; 17 | 18 | int 19 | getlen(char *const arr[]) 20 | { 21 | int i; 22 | 23 | for (i = 0; arr[i] != NULL; i++) 24 | ; 25 | 26 | return i; 27 | } 28 | 29 | int 30 | exec_execev(const char *filename, char *const argv[], char *const envp[]) 31 | { 32 | int fd; 33 | int len; 34 | char page[EXECPGSIZE]; 35 | 36 | fd = open(filename, O_RDONLY); 37 | if (fd < 0) { 38 | return -errno; 39 | } 40 | 41 | len = read(fd, page, EXECPGSIZE); 42 | if (len < 2) { 43 | return -ENOEXEC; 44 | } 45 | 46 | close(fd); 47 | 48 | if (len < EXECPGSIZE) 49 | page[len] = 0; 50 | 51 | if (page[0] == 0x7f && page[1] == 'E' && page[2] == 'L'&& page[3] == 'F') { 52 | int i; 53 | int arglen = getlen(argv); 54 | const char **new_argv = (const char **)malloc(sizeof(char *)*(arglen+4)); 55 | 56 | //printf("ELF!\n"); 57 | 58 | new_argv[0] = sandbox_path; 59 | new_argv[1] = ld_path; 60 | for (i = 0; i <= arglen; i++) 61 | new_argv[i + 2] = argv[i]; 62 | new_argv[arglen + 3] = NULL; 63 | 64 | /*for (i = 0; new_argv[i] != NULL; i++) 65 | printf("'%s' ", new_argv[i]); 66 | printf("\n");*/ 67 | 68 | int status = fork(); 69 | if (status < 0) 70 | return status; 71 | else if (status > 0) 72 | exit(0); 73 | 74 | execve(sandbox_path, (char* const*)new_argv, envp); 75 | // We can't handle this case currently... 76 | assert(false); 77 | 78 | return -errno; 79 | } 80 | 81 | if (page[0] == '#' || page[1] == '!') { 82 | bool no_args; 83 | int i; 84 | int arglen = getlen(argv); 85 | const char **new_argv = (const char **)malloc(sizeof(char *)*(arglen+7)); 86 | 87 | //printf("SHELL!\n"); 88 | 89 | // Parse interpreter and arguments. According to FreeBSD's historical 90 | // note in sys/kern/imgact_shell.c the most compatible behavoir is to 91 | // parse all interpreter arguements as a single argv into the 92 | // application. If there are no arguements the first arguement will be 93 | // the script itself. Parsing excess whitespace from the beginning and 94 | // end is optional and most systems do not do that. 95 | 96 | // Call sandbox with the following arguements: 97 | // /lib64/ld...