├── .gitignore ├── AUTHORS ├── COPYING ├── Makefile ├── README.md ├── common ├── bluepill.c ├── channel.c ├── exec_policy.c ├── log.c ├── time.c └── xchan.c ├── guest ├── asm.S ├── console.c ├── exec.c ├── init.c ├── mfn.c ├── schedule.c ├── shared_mem.c ├── symbols.c ├── timers.c ├── workqueue.c └── xchan.c ├── host ├── asm.S ├── breakpoint.c ├── capsule.c ├── ept.c ├── interrupt.c ├── memory.c ├── process.c ├── snapshot.c ├── symbols.c ├── time.c ├── transition.c ├── vm_exit.c ├── vmcs.c ├── vmx_instr.c └── xchan.c ├── include ├── common │ ├── bluepill.h │ ├── channel.h │ ├── cr4.h │ ├── error.h │ ├── exec_policy.h │ ├── locks.h │ ├── log.h │ ├── memory.h │ ├── mfn.h │ ├── params.h │ ├── shared_mem.h │ ├── snapshot_process.h │ ├── symbols.h │ ├── time.h │ ├── vmcall.h │ └── xchan.h ├── cuapi │ ├── common │ │ ├── exec_policy.h │ │ ├── kill.h │ │ ├── kill_msg.h │ │ ├── process.h │ │ ├── stats.h │ │ ├── uuid.h │ │ ├── vmcall.h │ │ └── xchan.h │ ├── error.h │ ├── guest │ │ ├── console.h │ │ ├── mfn.h │ │ └── xchan.h │ ├── log.h │ └── trusted │ │ ├── channel.h │ │ ├── mfn.h │ │ └── xchan.h ├── guest │ ├── console.h │ ├── init.h │ ├── kernel_sched_sched.h │ ├── mfn.h │ ├── process.h │ ├── shared_mem.h │ ├── symbols.h │ ├── timers.h │ └── xchan.h ├── host │ ├── breakpoint.h │ ├── capsule.h │ ├── context.h │ ├── ept.h │ ├── interrupt.h │ ├── memory.h │ ├── process.h │ ├── segment.h │ ├── snapshot.h │ ├── symbols.h │ ├── time.h │ ├── transition.h │ ├── traps.h │ ├── vcpu.h │ ├── vm_exit.h │ ├── vmcs.h │ ├── vmm.h │ ├── vmx.h │ └── xchan.h ├── shadow_process.h └── trusted │ ├── channel.h │ ├── fingerprint.h │ ├── mfn.h │ ├── time.h │ ├── vmm.h │ └── xchan.h ├── scripts ├── cappsule.lds └── obf.sh └── trusted ├── asm.S ├── cappsule.c ├── channel.c ├── create_capsule.c ├── exec_policy.c ├── fingerprint.c ├── mfn.c ├── shadowp.c ├── time.c ├── vmm.c └── xchan.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.ko 2 | *.o 3 | *.mod.c 4 | *.o.cmd 5 | *.ko.cmd 6 | .tmp_versions/ 7 | modules.order 8 | Module.symvers 9 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Authors: 2 | 3 | Gabriel Campana 4 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # The following macros affect compilation: 3 | # 4 | # -DRELEASE remove a lot of debug strings. 5 | # 6 | # Set corresponding environment variable to 1 do define them. 7 | # 8 | 9 | HV_MACROS := 10 | ifeq ($(RELEASE),1) 11 | HV_MACROS += -DRELEASE 12 | endif 13 | 14 | GIT_VERSION := $(shell \ 15 | if [ "x$(src)" != "x" ]; then \ 16 | git -C $(src) describe --always --tags; \ 17 | fi) 18 | ccflags-y := -I$(src)/include -DVERSION=\"$(GIT_VERSION)\" $(HV_MACROS) 19 | ldflags-y := -T$(src)/scripts/cappsule.lds -L$(src) 20 | obj-m := cappsule.o cappsule-guest.o 21 | 22 | cappsule-objs := \ 23 | common/bluepill.o \ 24 | common/channel.o \ 25 | common/exec_policy.o \ 26 | common/log.o \ 27 | common/time.o \ 28 | common/xchan.o \ 29 | host/asm.o \ 30 | host/breakpoint.o \ 31 | host/capsule.o \ 32 | host/ept.o \ 33 | host/interrupt.o \ 34 | host/memory.o \ 35 | host/process.o \ 36 | host/snapshot.o \ 37 | host/symbols.o \ 38 | host/time.o \ 39 | host/transition.o \ 40 | host/vm_exit.o \ 41 | host/vmcs.o \ 42 | host/vmx_instr.o \ 43 | host/xchan.o \ 44 | trusted/asm.o \ 45 | trusted/cappsule.o \ 46 | trusted/channel.o \ 47 | trusted/create_capsule.o\ 48 | trusted/exec_policy.o \ 49 | trusted/fingerprint.o \ 50 | trusted/mfn.o \ 51 | trusted/vmm.o \ 52 | trusted/shadowp.o \ 53 | trusted/time.o \ 54 | trusted/xchan.o 55 | 56 | cappsule-guest-objs := \ 57 | common/channel.o \ 58 | guest/asm.o \ 59 | guest/console.o \ 60 | guest/exec.o \ 61 | guest/init.o \ 62 | guest/mfn.o \ 63 | guest/schedule.o \ 64 | guest/shared_mem.o \ 65 | guest/symbols.o \ 66 | guest/timers.o \ 67 | guest/workqueue.o \ 68 | guest/xchan.o \ 69 | 70 | KDIR := /lib/modules/$(shell uname -r)/build 71 | PWD := $(shell pwd) 72 | 73 | all: 74 | $(MAKE) -C $(KDIR) M=$(PWD) modules 75 | 76 | clean: 77 | $(MAKE) -C $(KDIR) M=$(PWD) clean 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cappsule's hypervisor 2 | 3 | This repository is part of [Cappsule](https://github.com/cappsule), and contains 4 | the hypervisor. Please refer to the 5 | [documentation](https://github.com/cappsule/cappsule-doc/) for more information. 6 | 7 | 8 | 9 | ## Overview 10 | 11 | CPU and memory are virtualized thanks to hardware virtualization technology 12 | (Intel VT-x and EPT). During the launch of the hypervisor, the running OS is 13 | *bluepilled* and a snapshot of the memory is done. 14 | 15 | The hypervisor supports 2 kinds of VM: 16 | 17 | - the *trusted guest* (1 instance): this is the bluepilled OS, which has no 18 | restrictions. 19 | - the cappsules (0 to n instances): no access to the hardware is allowed, and 20 | the memory is a copy-on-write version of the snapshot. 21 | 22 | In order to operate, Cappsule needs to insert 2 kernel modules (`cappsule.ko` 23 | and `cappsule_guest.ko`). A userland daemon (in the 24 | [userland repository](https://github.com/cappsule/cappsule-userland/)) is 25 | responsible of the communication between userland and the kernel module. 26 | 27 | 28 | ## Architecture 29 | 30 | - `common/`: code shared between trusted guest / host / cappsule. 31 | - `guest/`: cappsules. This code is considered unsafe and is **not** trusted by 32 | the hypervisor. This code is executed in VMX non-root mode. 33 | - `host/`: hypervisor. This code is executed in VMX root mode. 34 | - `include/`: everything under `cuapi/` can be included both from the hypervisor 35 | and the userland repositories. 36 | - `trusted/`: *trusted guest*. This code is executed in VMX non-root mode, but 37 | is trusted by the hypervisor. 38 | -------------------------------------------------------------------------------- /common/channel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "common/locks.h" 21 | #include "common/symbols.h" 22 | #include "common/vmcall.h" 23 | #include "guest/shared_mem.h" 24 | #include "trusted/channel.h" 25 | #include "cuapi/error.h" 26 | #include "cuapi/common/vmcall.h" 27 | 28 | /* Put these functions in a special section, to prevent hypervisor from erasing 29 | * them. */ 30 | #define ATTR_SECTION __attribute__((section(".keep.common"))) 31 | 32 | 33 | /* Ensure that some locks aren't held by the kernel before snapshot, because 34 | * they might never be released if processes holding them aren't allowed to run 35 | * in the guest. 36 | * 37 | * Locks held by the hypervisor in this function must be released both by the 38 | * guest and the hypervisor with release_locks_after_snapshot(). */ 39 | static void take_locks_before_snapshot(void) 40 | { 41 | /* If module_mutex is held during snapshot, there's no garantee that the 42 | * process holding the lock will be allowed to run and release it. If 43 | * module_mutex is held, capsules can't load module, list modules, 44 | * etc. */ 45 | mutex_lock(&module_mutex); 46 | 47 | /* If uevent_sock_mutex is held, mfn_register() gets stuck in guest 48 | * because kobject_get_path() relies on it. */ 49 | mutex_lock(_uevent_sock_mutex); 50 | } 51 | 52 | /** 53 | * Call VMCALL_SNAPSHOT to create snapshot. 54 | * 55 | * This function is special: the code executed after the vmcall might either be 56 | * in trusted guest or in a capsule. If vmcall's return value is negative, it 57 | * tells that the code is executed in a capsule. 58 | */ 59 | static ATTR_SECTION unsigned long channel_snapshot(unsigned long arg) 60 | { 61 | struct cappsule_ioc_snapshot __user *u_snapshot; 62 | unsigned int capsule_id; 63 | struct cappsule_ioc_snapshot s; 64 | unsigned long errno; 65 | err_t err; 66 | 67 | u_snapshot = (struct cappsule_ioc_snapshot __user *)arg; 68 | if (copy_from_user(&s, u_snapshot, sizeof(s)) != 0) 69 | return -EFAULT; 70 | 71 | take_locks_before_snapshot(); 72 | 73 | err = cpu_vmcs_vmcall3_ret(VMCALL_SNAPSHOT, (unsigned long)s.params, 74 | s.params_size); 75 | 76 | if ((int)err < 0) { 77 | /* guest_init() has already been executed */ 78 | capsule_id = guest_get_capsule_id(); 79 | put_user(capsule_id, &u_snapshot->result_capsule_id); 80 | errno = 1; 81 | } else { 82 | release_locks_after_snapshot(); 83 | if (err == 0) { 84 | errno = 0; 85 | } else { 86 | /* The cast of (unsigned long)err is required, otherwise 87 | * -err is a 32bit integer. */ 88 | errno = -(CAPPSULE_ERRNO_BASE + (unsigned long)err); 89 | } 90 | } 91 | 92 | return errno; 93 | } 94 | 95 | long ATTR_SECTION common_channel_ioctl(struct file *file, unsigned int cmd, 96 | unsigned long arg) 97 | { 98 | 99 | if (cmd == CAPPSULE_IOC_SNAPSHOT) 100 | return channel_snapshot(arg); 101 | 102 | return trusted_channel_ioctl(file, cmd, arg); 103 | } 104 | -------------------------------------------------------------------------------- /common/exec_policy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | 19 | #include "common/exec_policy.h" 20 | 21 | 22 | static struct exec_policies *exec_policies; 23 | 24 | 25 | struct exec_policies *get_exec_policies(void) 26 | { 27 | return exec_policies; 28 | } 29 | 30 | void set_exec_policies(struct exec_policies *p) 31 | { 32 | exec_policies = p; 33 | } 34 | -------------------------------------------------------------------------------- /common/time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | 19 | #include "common/log.h" 20 | #include "common/time.h" 21 | #include "host/capsule.h" 22 | #include "host/time.h" 23 | #include "host/vcpu.h" 24 | #include "trusted/time.h" 25 | 26 | 27 | /* Can be called both in VMX root mode and VMX non root-mode. 28 | * 29 | * The idea of switching capsule->clock_timer.function at each capsule / 30 | * trusted guest transition is appealing, but it's broken. Let A and B be 2 31 | * capsules pinned to CPU 1, A is not running and B is running. We would have 32 | * the following timer functions: 33 | * - A->clock_timer.function = trusted_clock_event_function; 34 | * - B->clock_timer.function = capsule_clock_event_function; 35 | * 36 | * If B->clock_timer expires, an external interrupt triggers a VM-exit and the 37 | * hypervisor calls the IRQ handler of LOCAL_TIMER_INTERRUPT. 38 | * capsule_clock_event_function is called. If A->clock_timer has also expired, 39 | * trusted_clock_event_function is also called which is wrong. */ 40 | enum hrtimer_restart clock_event_function(struct hrtimer *timer) 41 | { 42 | enum hrtimer_restart ret; 43 | struct capsule *capsule; 44 | unsigned int cpu; 45 | 46 | capsule = container_of(timer, struct capsule, clock_timer); 47 | 48 | /* interrupt is received on the same CPU that set the clock timer */ 49 | cpu = smp_processor_id(); 50 | if (cpu != capsule->vcpu->cpu) { 51 | hv_dbg("%s: BUG", __func__); 52 | return HRTIMER_NORESTART; 53 | } 54 | 55 | /* If CPU is in VMX root mode, this is straightforward. Otherwise, this 56 | * function is called in IRQ context, in trusted guest. The capsule 57 | * isn't running. */ 58 | 59 | if (capsule->vcpu->guest == GUEST_CAPSULE) { 60 | /* VMX root mode */ 61 | ret = capsule_clock_event_function(capsule); 62 | } else { 63 | /* VMX non-root mode */ 64 | ret = trusted_clock_event_function(capsule); 65 | } 66 | 67 | return ret; 68 | } 69 | -------------------------------------------------------------------------------- /common/xchan.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | 19 | #include "common/vmcall.h" 20 | #include "common/xchan.h" 21 | #include "host/interrupt.h" 22 | #include "host/vcpu.h" 23 | #include "host/vmm.h" 24 | 25 | 26 | /* Can be called both in VMX root mode and VMX non root-mode. 27 | * 28 | * Wake up shadow process if capsule isn't running, otherwise inject pending 29 | * interrupt. */ 30 | void cpu_xchan_notify_guest(void *arg) 31 | { 32 | struct xchan_pending_intr *intr; 33 | unsigned long reason; 34 | unsigned int cpu, id; 35 | struct vcpu *vcpu; 36 | __u8 vector; 37 | int ret; 38 | 39 | cpu = smp_processor_id(); 40 | vcpu = &vmm.vcpus[cpu]; 41 | 42 | intr = (struct xchan_pending_intr *)arg; 43 | id = intr->capsule_id; 44 | vector = intr->vector; 45 | 46 | if (vcpu->guest == GUEST_CAPSULE) { 47 | /* VMX root mode */ 48 | ret = host_add_pending_xchan_intr(vcpu, id, vector); 49 | } else { 50 | /* VMX non-root mode */ 51 | reason = VMCALL_ADD_PENDING_XCHAN_INTR; 52 | ret = cpu_vmcs_vmcall3_ret(reason, id, vector); 53 | } 54 | 55 | intr->error = ret; 56 | } 57 | -------------------------------------------------------------------------------- /guest/asm.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | .code64 4 | 5 | ENTRY(fake_return_stub) 6 | pop %rcx 7 | pop %r11 8 | pop %r10 9 | pop %r9 10 | pop %r8 11 | pop %rax 12 | pop %rdx 13 | pop %rsi 14 | pop %rdi 15 | 16 | /* This stub returns right after a vmcall instruction. Clear ZF and CF 17 | * otherwise guest may think that vmcall failed. */ 18 | test %rsp, %rsp 19 | 20 | ret 21 | END(fake_return_stub) 22 | 23 | ENTRY(guest_schedule_end_stub) 24 | call guest_schedule_end 25 | test %rax, %rax 26 | jne 1f 27 | ret 28 | 1: /* call_schedule_again */ 29 | jmp *___schedule 30 | END(guest_schedule_end_stub) 31 | 32 | ENTRY(guest_schedule_tail_end_stub) 33 | call guest_schedule_tail_end 34 | ret 35 | END(guest_schedule_tail_end_stub) 36 | 37 | ENTRY(guest_do_exit_stub) 38 | push %rax 39 | push %rdi 40 | call guest_do_exit 41 | pop %rdi 42 | pop %rax 43 | jmp *%rax 44 | END(guest_do_exit_stub) 45 | 46 | ENTRY(guest_prepare_binprm_stub) 47 | /* hypervisor moved hijacked rip into rax */ 48 | push %rax 49 | /* save rdi */ 50 | push %rdi 51 | /* call guest_prepare_binprm */ 52 | call guest_prepare_binprm 53 | pop %rdi 54 | test %eax, %eax 55 | jne 1f 56 | /* jmp to hijacked rip */ 57 | ret 58 | 1: /* execve_forbidden */ 59 | /* don't restore rax: keep return value from guest_prepare_binprm */ 60 | pop %rdi 61 | /* hijacked rip was pushed on stack, return to callee */ 62 | ret 63 | END(guest_prepare_binprm_stub) 64 | 65 | ENTRY(process_one_work_stub) 66 | /* save return address given by the hypervisor */ 67 | push %rax 68 | /* save arguments */ 69 | push %rdi 70 | push %rsi 71 | call filter_workqueue 72 | /* restore arguments */ 73 | pop %rsi 74 | pop %rdi 75 | /* get return address */ 76 | pop %rax 77 | /* return to process_one_work */ 78 | jmp *%rax 79 | END(process_one_work_stub) 80 | -------------------------------------------------------------------------------- /guest/exec.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "common/exec_policy.h" 27 | #include "common/vmcall.h" 28 | #include "guest/shared_mem.h" 29 | 30 | 31 | static struct exec_policy *get_policy(struct exec_policies *policies, 32 | struct uuid *uuid) 33 | { 34 | struct exec_policy *policy; 35 | unsigned int *offsets; 36 | unsigned int i; 37 | 38 | offsets = (unsigned int *)policies->data; 39 | for (i = 0; i < policies->n; i++) { 40 | policy = (struct exec_policy *)(policies->data + offsets[i]); 41 | if (memcmp(&policy->uuid, uuid, sizeof(policy->uuid)) == 0) 42 | return policy; 43 | } 44 | 45 | return NULL; 46 | } 47 | 48 | /* get path i from policy */ 49 | static inline char *get_path(struct exec_policy *policy, unsigned int i) 50 | { 51 | unsigned int *offsets; 52 | 53 | offsets = (unsigned int *)policy->data; 54 | 55 | return (char *)(policy->data + offsets[i]); 56 | } 57 | 58 | static int check_path(const char *policy_path, const char *path) 59 | { 60 | size_t len; 61 | 62 | len = strlen(policy_path); 63 | if (len >= 2 && strncmp(policy_path + len - 2, "/*", 2) == 0) { 64 | if (strncmp(policy_path, path, len - 1) == 0 && 65 | strchr(path + len - 1, '/') == NULL) 66 | return 1; 67 | } else if (len >= 3 && strncmp(policy_path + len - 3, "/**", 3) == 0) { 68 | if (strncmp(policy_path, path, len - 2) == 0) 69 | return 1; 70 | } else { 71 | if (strcmp(path, policy_path) == 0) 72 | return 1; 73 | } 74 | 75 | return 0; 76 | } 77 | 78 | /* heavily modified version of ap_getparents() */ 79 | static void getparents(char *path) 80 | { 81 | char *p, *q; 82 | 83 | /* a) remove ./ path segments */ 84 | p = q = path; 85 | while (*q != '\x00') { 86 | if (q[0] == '/' && q[1] == '.' && q[2] == '/') 87 | q += 2; 88 | else 89 | *p++ = *q++; 90 | } 91 | 92 | /* b) remove trailing . path, segment */ 93 | if (p[-1] == '.' && p[-2] == '/') 94 | p--; 95 | *p = '\x00'; 96 | 97 | /* c) remove all xx/../ segments */ 98 | p = q = path; 99 | while (*q != '\x00') { 100 | if (q[0] == '/' && q[1] == '.' && q[2] == '.' && q[3] == '/') { 101 | if (p != path) { 102 | do { 103 | p--; 104 | } while (*p != '/'); 105 | } 106 | q += 3; 107 | 108 | } else { 109 | *p++ = *q++; 110 | } 111 | } 112 | *p = '\x00'; 113 | 114 | /* d) remove trailing xx/.. segment. */ 115 | if (p[-1] == '.' && p[-2] == '.' && p[-3] == '/') { 116 | if (p == path + 3) { 117 | path[1] = '\x00'; 118 | } else { 119 | p -= 3; 120 | do { 121 | p--; 122 | } while (*p != '/'); 123 | p[1] = '\x00'; 124 | } 125 | } 126 | } 127 | 128 | static void no2slash(char *path) 129 | { 130 | char *d, *p; 131 | 132 | p = d = path; 133 | while (*p != '\x00') { 134 | *d++ = *p; 135 | if (*p == '/') { 136 | do { 137 | p++; 138 | } while (*p == '/'); 139 | } 140 | else { 141 | p++; 142 | } 143 | } 144 | 145 | *d = '\x00'; 146 | } 147 | 148 | static char *canonical_path(const char *path) 149 | { 150 | char *cpath; 151 | 152 | cpath = kstrdup(path, GFP_KERNEL); 153 | if (cpath == NULL) 154 | return NULL; 155 | 156 | no2slash(cpath); 157 | getparents(cpath); 158 | 159 | return cpath; 160 | } 161 | 162 | /* check if path is allowed for policy id. 163 | * 164 | * called from guest.*/ 165 | static int guest_exec_allowed(struct exec_policies *policies, 166 | struct uuid *uuid, 167 | const char *path) 168 | { 169 | struct exec_policy *policy; 170 | const char *policy_path; 171 | unsigned int i; 172 | char *cpath; 173 | int allowed; 174 | 175 | policy = get_policy(policies, uuid); 176 | if (policy == NULL) 177 | return 0; 178 | 179 | /* path should be absolute and canonical, anyway... */ 180 | if (path[0] != '/') 181 | return 0; 182 | 183 | cpath = canonical_path(path); 184 | if (cpath == NULL) 185 | return 0; 186 | 187 | allowed = 0; 188 | for (i = 0; i < policy->n; i++) { 189 | policy_path = get_path(policy, i); 190 | if (check_path(policy_path, cpath)) { 191 | allowed = 1; 192 | break; 193 | } 194 | 195 | } 196 | 197 | kfree(cpath); 198 | return allowed; 199 | } 200 | 201 | /* called from guest. 202 | * 203 | * Yes, guest is responsible of execve check. It makes no difference to do this 204 | * check from hypervisor than from guest: a compromised guest kernel can bypass 205 | * this check easily (eg: by modifying stub_execve address in sys_call_table). 206 | * 207 | * Since it's way more complicated and dangerous to do this check from 208 | * hypervisor (because guest memory must be read), let guest check execve 209 | * arguments. 210 | * 211 | * 212 | * execve can't be hooked directly, because execlp(), execvp(), and execvpe() 213 | * may try to execve different paths before succeed. The capsule must not be 214 | * killed on non-existent path. 215 | * 216 | * In consequence, hook prepare_binprm() which is called after open_exec(). */ 217 | int guest_prepare_binprm(struct linux_binprm *bprm) 218 | { 219 | /* static variable */ 220 | static int guest_first_execve = 1; 221 | 222 | struct exec_policies *exec_policies; 223 | struct uuid uuid; 224 | char *buf, *path; 225 | int allowed, ret; 226 | size_t size; 227 | 228 | size = 4096; 229 | buf = kmalloc(size, GFP_KERNEL); 230 | if (buf == NULL) 231 | return -ENOMEM; 232 | 233 | path = dentry_path_raw(bprm->file->f_path.dentry, buf, size); 234 | if (IS_ERR(path)) { 235 | kfree(buf); 236 | return -EINVAL; 237 | } 238 | 239 | /* Path is resolved by dentry_path_raw(), there's no issue with symlink. 240 | * Execution of a script triggers 2 calls to this function: 241 | * /path/to/script.sh and /bin/sh. */ 242 | 243 | exec_policies = shared_mem->exec_policies; 244 | guest_get_self_policy_uuid(&uuid); 245 | 246 | /* Always allow execution of wrapper (capsule_init), which is the first 247 | * execve. This trick avoids to put wrapper path in every policy 248 | * configuration file. */ 249 | if (guest_first_execve) { 250 | guest_first_execve = 0; 251 | allowed = 1; 252 | } else { 253 | allowed = guest_exec_allowed(exec_policies, &uuid, path); 254 | } 255 | 256 | printk(KERN_ERR "execve in capsule: %s (allowed=%d)\n", path, allowed); 257 | kfree(buf); 258 | 259 | if (!allowed) { 260 | ret = -EPERM; 261 | if (0) 262 | cpu_vmcs_vmcall(VMCALL_FORBIDDEN_EXECVE, 0); 263 | } else { 264 | ret = 0; 265 | } 266 | 267 | return ret; 268 | } 269 | -------------------------------------------------------------------------------- /guest/init.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "common/locks.h" 22 | #include "cuapi/common/process.h" 23 | #include "guest/console.h" 24 | #include "guest/init.h" 25 | #include "guest/mfn.h" 26 | #include "guest/process.h" 27 | #include "guest/shared_mem.h" 28 | #include "guest/symbols.h" 29 | #include "guest/timers.h" 30 | #include "guest/xchan.h" 31 | 32 | MODULE_LICENSE("GPL"); 33 | MODULE_VERSION(VERSION); 34 | 35 | #define NET_SECRET_SIZE (MD5_MESSAGE_BYTES / 4) 36 | 37 | 38 | static void disable_pid(enum pid_index pid_index) 39 | { 40 | pid_t pid; 41 | 42 | pid = shared_mem->process.allowed_pids.pids[pid_index]; 43 | if (pid != -1) 44 | set_bit(pid, shared_mem->process.pid_bitmap); 45 | } 46 | 47 | /* called from guest (encapsulated): in fact, it's its first instructions. 48 | * 49 | * starts running with irq disabled. */ 50 | void guest_init(void) 51 | { 52 | guest_fix_timekeeping(); 53 | setup_timers(); 54 | 55 | /* Reinitialize net_secret. Differents capsule will not have identical, 56 | * source port, tcp seq numbers, etc. */ 57 | get_random_bytes(_net_secret, NET_SECRET_SIZE); 58 | 59 | init_apic(); 60 | 61 | setup_shared_mem(); 62 | 63 | /* don't allow guiclient to run if --no-gui is passed to virtexec */ 64 | if (shared_mem->no_gui) 65 | disable_pid(PID_INDEX_GUI); 66 | 67 | local_irq_enable(); 68 | 69 | release_locks_after_snapshot(); 70 | 71 | guest_mfn_init(); 72 | 73 | guest_xchan_init(shared_mem->xchan_first_vector); 74 | 75 | guest_tty_init(); 76 | 77 | /* return to fake_return_stub which returns to saved rip */ 78 | //printk(KERN_ERR "return from %s\n", __func__); 79 | } 80 | 81 | EXPORT_SYMBOL(guest_init); 82 | 83 | static int __init cappsule_guest_init(void) 84 | { 85 | err_t error; 86 | 87 | error = resolve_symbols(guest_symbols); 88 | if (error != SUCCESS) { 89 | /* errno is set to the value returned by the init function */ 90 | return -(CAPPSULE_ERRNO_BASE + error); 91 | } 92 | 93 | error = resolve_per_cpu_symbols(guest_per_cpu_symbols); 94 | if (error != SUCCESS) 95 | return -(CAPPSULE_ERRNO_BASE + error); 96 | 97 | return 0; 98 | } 99 | 100 | static void __exit cappsule_guest_exit(void) 101 | { 102 | 103 | } 104 | 105 | module_init(cappsule_guest_init); 106 | module_exit(cappsule_guest_exit); 107 | -------------------------------------------------------------------------------- /guest/mfn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "guest/init.h" 23 | #include "guest/mfn.h" 24 | #include "common/memory.h" 25 | 26 | 27 | static long ioctl(struct file *file, unsigned int cmd, unsigned long arg) 28 | { 29 | unsigned long pfn, uaddr; 30 | long ret; 31 | 32 | /* /dev/mfn is owned by root and the permissions are 0600. Anyway, it 33 | * doesn't hurt to check privileges. */ 34 | if (!capable(CAP_SYS_RAWIO)) 35 | return -EPERM; 36 | 37 | if (_IOC_TYPE(cmd) != MFN_IOC_MAGIC) 38 | return -ENOTTY; 39 | 40 | switch (cmd) { 41 | case MFN_GET: 42 | uaddr = arg; 43 | pfn = uaddr_pfn(read_cr3(), uaddr); 44 | ret = (pfn != 0) ? (long)pfn : -EINVAL; 45 | break; 46 | 47 | default: 48 | ret = -EINVAL; 49 | } 50 | 51 | return ret; 52 | } 53 | 54 | static int close(struct inode *inode, struct file *file) 55 | { 56 | return 0; 57 | } 58 | 59 | static const struct file_operations mfn_fops = { 60 | .owner = THIS_MODULE, 61 | .release = close, 62 | .unlocked_ioctl = ioctl, 63 | .llseek = default_llseek, 64 | }; 65 | 66 | static struct miscdevice mfn_dev = { 67 | .minor = MISC_DYNAMIC_MINOR, 68 | .name = GUEST_MFN_DEVICE_NAME, 69 | .fops = &mfn_fops, 70 | }; 71 | 72 | void guest_mfn_init(void) 73 | { 74 | if (misc_register(&mfn_dev) != 0) 75 | guest_error("failed to register " GUEST_MFN_DEVICE_NAME " device"); 76 | } 77 | -------------------------------------------------------------------------------- /guest/schedule.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "common/vmcall.h" 27 | #include "guest/init.h" 28 | #include "guest/kernel_sched_sched.h" 29 | #include "guest/shared_mem.h" 30 | #include "guest/symbols.h" 31 | 32 | static int forbidden_process(struct task_struct *p) 33 | { 34 | if (p->pid >= shared_mem->process.max_pid) 35 | return 0; 36 | 37 | if (!test_bit(p->pid, shared_mem->process.pid_bitmap)) 38 | return 0; 39 | 40 | return 1; 41 | } 42 | 43 | /* called from guest when __schedule() returns. 44 | * don't let thread continue its execution if not expected */ 45 | int guest_schedule_end(void) 46 | { 47 | int allowed_to_run, ret; 48 | struct cfs_rq *cfs_rq; 49 | unsigned long flags; 50 | struct rq *rq; 51 | 52 | allowed_to_run = !forbidden_process(current); 53 | //printk(KERN_ERR "%s: %5d %s (%d)\n", __func__, current->pid, 54 | // current->comm, allowed_to_run); 55 | 56 | if (allowed_to_run) { 57 | ret = 0; 58 | } else { 59 | /* Setting task state to TASK_UNINTERRUPTIBLE doesn't always 60 | * prevent process to run again. On the contrary, removing 61 | * process from runqueue is effective. */ 62 | local_irq_save(flags); 63 | 64 | /* rq = task_rq(current); is not an option because runqueues 65 | * aren't exported */ 66 | cfs_rq = current->se.cfs_rq; 67 | rq = cfs_rq->rq; 68 | 69 | _deactivate_task(rq, current, 0); 70 | local_irq_restore(flags); 71 | 72 | /* __schedule() will be called again */ 73 | ret = -1; 74 | } 75 | 76 | return ret; 77 | } 78 | 79 | /* A process may fork during snapshot (ie: parent is in fork syscall and child 80 | * isn't created yet), and its child is not present in pid_bitmap. 81 | * 82 | * A newly forked process directly context switches into ret_from_fork, which 83 | * calls schedule_tail(). Hook schedule_tail() and forbid process to run if not 84 | * allowed to. ret_from_fork isn't hooked directly to allow schedule_tail() to 85 | * executes. */ 86 | void guest_schedule_tail_end(void) 87 | { 88 | //printk(KERN_ERR "%s: %s %d\n", __func__, current->comm, current->pid); 89 | 90 | /* Force child to schedule(). If child isn't allowed to run, it will be 91 | * removed from runqueue thanks to guest_schedule_end(). */ 92 | if (forbidden_process(current)) 93 | schedule(); 94 | } 95 | 96 | void guest_do_exit(int exit_code) 97 | { 98 | printk(KERN_ERR "do_exit(%d) (%s)\n", exit_code, current->comm); 99 | 100 | if (current == shared_mem->process.capsule_task) 101 | cpu_vmcs_vmcall(VMCALL_EXIT, 0); 102 | } 103 | -------------------------------------------------------------------------------- /guest/shared_mem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | 19 | #include "common/vmcall.h" 20 | #include "guest/init.h" 21 | #include "guest/shared_mem.h" 22 | 23 | struct shared_mem *shared_mem; 24 | 25 | 26 | unsigned int guest_get_capsule_id(void) 27 | { 28 | return shared_mem->capsule_id; 29 | } 30 | 31 | /* never used by cappsule.ko, but required */ 32 | EXPORT_SYMBOL(guest_get_capsule_id); 33 | 34 | void setup_shared_mem(void) 35 | { 36 | unsigned long gpa, page; 37 | 38 | page = __get_free_page(GFP_ATOMIC); 39 | if (page == 0) 40 | guest_error("allocation failed"); 41 | 42 | /* force host to allocate pages */ 43 | trigger_ept_violation(page); 44 | 45 | gpa = __pa(page); 46 | cpu_vmcs_vmcall(VMCALL_SHARE_MEM, gpa); 47 | 48 | shared_mem = (struct shared_mem *)page; 49 | } 50 | 51 | /* This function is required by cappsule-guest.ko, even if it's never 52 | * called. */ 53 | long trusted_channel_ioctl(struct file *file, unsigned int cmd, 54 | unsigned long arg) 55 | { 56 | return -1; 57 | } 58 | -------------------------------------------------------------------------------- /guest/symbols.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include "guest/symbols.h" 18 | 19 | 20 | u32 *_net_secret; 21 | struct mutex *_uevent_sock_mutex; 22 | 23 | void (*_irq_set_chip_and_handler_name)(unsigned int, struct irq_chip *, 24 | irq_flow_handler_t, const char *); 25 | void (*_deactivate_task)(struct rq *rq, struct task_struct *p, int flags); 26 | void (*___schedule)(void); 27 | struct tick_device *(*_tick_get_device)(int cpu); 28 | 29 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) 30 | struct tvec_base *_tvec_bases[NR_CPUS]; 31 | #else 32 | struct tvec_base **_tvec_bases[NR_CPUS]; 33 | #endif 34 | 35 | struct symbol guest_symbols[] = { 36 | SYMBOL(deactivate_task), 37 | SYMBOL(irq_set_chip_and_handler_name), 38 | SYMBOL(net_secret), 39 | SYMBOL(__schedule), 40 | SYMBOL(tick_get_device), 41 | SYMBOL(uevent_sock_mutex), 42 | { NULL, NULL } 43 | }; 44 | 45 | struct per_cpu_symbol guest_per_cpu_symbols[] = { 46 | PER_CPU_SYMBOL(tvec_bases), 47 | { NULL, NULL } 48 | }; 49 | 50 | EXPORT_SYMBOL(___schedule); 51 | 52 | extern void guest_do_exit_stub(void); 53 | EXPORT_SYMBOL(guest_do_exit_stub); 54 | 55 | extern void guest_schedule_end_stub(void); 56 | EXPORT_SYMBOL(guest_schedule_end_stub); 57 | 58 | extern void guest_schedule_tail_end_stub(void); 59 | EXPORT_SYMBOL(guest_schedule_tail_end_stub); 60 | 61 | extern void guest_prepare_binprm_stub(void); 62 | EXPORT_SYMBOL(guest_prepare_binprm_stub); 63 | 64 | extern void fake_return_stub(void); 65 | EXPORT_SYMBOL(fake_return_stub); 66 | 67 | extern void process_one_work_stub(void); 68 | EXPORT_SYMBOL(process_one_work_stub); 69 | -------------------------------------------------------------------------------- /guest/timers.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "guest/init.h" 26 | #include "guest/timers.h" 27 | #include "guest/symbols.h" 28 | #include "common/vmcall.h" 29 | 30 | /* c1797baf6880174f899ce3960d0598f5bbeeb7ff 31 | * tick: Move core only declarations and functions to core */ 32 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) 33 | enum tick_device_mode { 34 | TICKDEV_MODE_PERIODIC, 35 | TICKDEV_MODE_ONESHOT, 36 | }; 37 | 38 | struct tick_device { 39 | struct clock_event_device *evtdev; 40 | enum tick_device_mode mode; 41 | }; 42 | #endif 43 | 44 | #define TVN_BITS (CONFIG_BASE_SMALL ? 4 : 6) 45 | #define TVR_BITS (CONFIG_BASE_SMALL ? 6 : 8) 46 | #define TVN_SIZE (1 << TVN_BITS) 47 | #define TVR_SIZE (1 << TVR_BITS) 48 | 49 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) 50 | /* commit: 1dabbcec2c0a36fe43509d06499b9e512e70a028 51 | * timer: Use hlist for the timer wheel hash buckets */ 52 | #define LIST_TYPE struct hlist_head 53 | #define LIST_FOR_EACH_ENTRY hlist_for_each_entry 54 | #else 55 | #define LIST_TYPE struct list_head 56 | #define LIST_FOR_EACH_ENTRY list_for_each_entry 57 | #endif 58 | 59 | struct tvec { 60 | LIST_TYPE vec[TVN_SIZE]; 61 | }; 62 | 63 | struct tvec_root { 64 | LIST_TYPE vec[TVR_SIZE]; 65 | }; 66 | 67 | struct tvec_base { 68 | spinlock_t lock; 69 | struct timer_list *running_timer; 70 | unsigned long timer_jiffies; 71 | unsigned long next_timer; 72 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) 73 | /* commit: 99d5f3aac674fe081ffddd2dbb8946ccbc14c410 74 | * timers: Add accounting of non deferrable timers */ 75 | unsigned long active_timers; 76 | #endif 77 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,5) 78 | /* commit: fff421580f512fc044cc7421fdff31a7a6997350 79 | * timers: Track total number of timers in list */ 80 | unsigned long all_timers; 81 | #endif 82 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,3) 83 | /* commit: d6f93829811a3e74f58e3c3823d507411eed651a 84 | * timer: Store cpu-number in struct tvec_base */ 85 | int cpu; 86 | #endif 87 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) 88 | /* commit: bc7a34b8b9ebfb0f4b8a35a72a0b134fd6c5ef50 89 | * timer: Reduce timer migration overhead if disabled */ 90 | bool migration_enabled; 91 | /* commit: 683be13a284720205228e29207ef11a1c3c322b9 92 | * timer: Minimize nohz off overhead */ 93 | bool nohz_active; 94 | #endif 95 | struct tvec_root tv1; 96 | struct tvec tv2; 97 | struct tvec tv3; 98 | struct tvec tv4; 99 | struct tvec tv5; 100 | } ____cacheline_aligned; 101 | 102 | 103 | static const char *timer_name[] = { 104 | "delayed_work_timer_fn+0x0", 105 | "commit_timeout+0x0", 106 | "wakeup_timer_fn+0x0", 107 | "idle_worker_timeout+0x0", 108 | "process_timeout+0x0", 109 | "mce_start_timer+0x0", 110 | NULL, 111 | }; 112 | 113 | static void do_nothing(unsigned long data) 114 | { 115 | } 116 | 117 | static int allowed_timer(char *name) 118 | { 119 | const char **p; 120 | 121 | for (p = timer_name; *p != NULL; p++) 122 | if (strcmp(*p, name) == 0) 123 | return 1; 124 | 125 | return 0; 126 | } 127 | 128 | static void filter_timer_list(LIST_TYPE *head) 129 | { 130 | struct timer_list *timer; 131 | char name[512], *p; 132 | int allowed; 133 | 134 | LIST_FOR_EACH_ENTRY(timer, head, entry) { 135 | sprint_symbol(name, (unsigned long)timer->function); 136 | if ((p = strchr(name, '/')) != NULL) 137 | *p = '\x00'; 138 | 139 | allowed = allowed_timer(name); 140 | //printk(KERN_ERR "%s timer %s" 141 | // allowed ? "keeping " : "removing", name); 142 | 143 | /* timer could be deleted, but it's difficult because 144 | * detach_expired_timer() isn't exported */ 145 | if (!allowed) 146 | timer->function = do_nothing; 147 | } 148 | } 149 | 150 | /* XXX: temporary solution. May need some cleanup. How does /proc/timer_list 151 | * works? 152 | * 153 | * Required, otherwise hardware timers (network card for example) may expire */ 154 | void setup_timers(void) 155 | { 156 | struct tvec_base *base; 157 | int i; 158 | 159 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) 160 | base = _tvec_bases[smp_processor_id()]; 161 | #else 162 | base = *_tvec_bases[smp_processor_id()]; 163 | #endif 164 | 165 | for (i = 0; i < TVR_SIZE; i++) 166 | filter_timer_list(base->tv1.vec + i); 167 | 168 | for (i = 0; i < TVN_SIZE; i++) { 169 | filter_timer_list(base->tv2.vec + i); 170 | filter_timer_list(base->tv3.vec + i); 171 | filter_timer_list(base->tv4.vec + i); 172 | filter_timer_list(base->tv5.vec + i); 173 | } 174 | } 175 | 176 | /* called from guest 177 | * 178 | * Guest time is already accurate, but if timekeeping.cycle_last is not up to 179 | * date, timespec_add_ns() takes a hundred of seconds (!) to return (because of 180 | * a 64 bits overflow). */ 181 | void guest_fix_timekeeping(void) 182 | { 183 | struct timespec ts; 184 | struct timeval tv; 185 | int ret; 186 | 187 | tv.tv_sec = 0; 188 | tv.tv_usec = 0; 189 | cpu_vmcs_vmcall2(VMCALL_GETTIMEOFDAY, 0, &tv.tv_sec, &tv.tv_usec); 190 | 191 | /* do_gettimeofday sets a struct timeval but do_settimeofday expects a 192 | * struct timespec */ 193 | ts.tv_sec = tv.tv_sec; 194 | ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC; 195 | 196 | /* XXX: oops_in_progress is set to 1 to avoid annoying warning (because 197 | * IRQs are enabled). Callstack: 198 | * 199 | * do_settimeofday 200 | * clock_was_set 201 | * on_each_cpu 202 | * smp_call_function 203 | * smp_call_function_many 204 | * 205 | * WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled() 206 | * && !oops_in_progress && !early_boot_irqs_disabled); */ 207 | oops_in_progress = 1; 208 | ret = do_settimeofday(&ts); 209 | oops_in_progress = 0; 210 | 211 | if (ret != 0) 212 | guest_error("settimeofday failed"); 213 | } 214 | 215 | static u32 null_apic_read(u32 reg) 216 | { 217 | return 0; 218 | } 219 | 220 | static void null_apic_write(u32 reg, u32 v) 221 | { 222 | } 223 | 224 | static int handle_lapic_next_event(unsigned long delta, 225 | struct clock_event_device *evt) 226 | { 227 | __u64 nsec; 228 | 229 | nsec = (delta << evt->shift) / evt->mult; 230 | cpu_vmcs_vmcall(VMCALL_SET_TIMER, nsec); 231 | 232 | return 0; 233 | } 234 | 235 | void init_apic(void) 236 | { 237 | struct clock_event_device *levt; 238 | struct tick_device *dev; 239 | 240 | dev = _tick_get_device(smp_processor_id()); 241 | levt = dev->evtdev; 242 | 243 | levt->set_next_event = handle_lapic_next_event; 244 | /* XXX: .broadcast? */ 245 | 246 | apic->read = null_apic_read; 247 | apic->write = null_apic_write; 248 | } 249 | -------------------------------------------------------------------------------- /guest/workqueue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | struct worker; 23 | 24 | 25 | static void dummy(struct work_struct *work) 26 | { 27 | } 28 | 29 | static const char *workqueues_name[] = { 30 | "flush_to_ldisc", /* tty */ 31 | "vmstat_update", /* update of /proc/vmstat */ 32 | /* bdi_writeback_workfn is specially handled */ 33 | NULL 34 | }; 35 | 36 | static int keep_bdi_writeback(struct work_struct *work) 37 | { 38 | struct backing_dev_info *bdi; 39 | struct bdi_writeback *wb; 40 | 41 | wb = container_of(to_delayed_work(work), struct bdi_writeback, dwork); 42 | bdi = wb->bdi; 43 | 44 | /* Pages from block devices may still be cached. Only allow fuse 45 | * devices. */ 46 | if (strcmp(bdi->name, "fuse") == 0) 47 | return 1; 48 | 49 | return 0; 50 | } 51 | 52 | static int keep_workqueue(const char *func_name, struct work_struct *work) 53 | { 54 | const char **name; 55 | 56 | for (name = workqueues_name; *name != NULL; name++) { 57 | if (strcmp(*name, func_name) == 0) 58 | return 1; 59 | } 60 | 61 | if (strcmp(func_name, "bdi_writeback_workfn") == 0) 62 | return keep_bdi_writeback(work); 63 | 64 | return 0; 65 | } 66 | 67 | void filter_workqueue(struct worker *worker, struct work_struct *work) 68 | { 69 | char name[512], *p; 70 | 71 | sprint_symbol(name, (long unsigned int)work->func); 72 | p = strchr(name, '+'); 73 | if (p != NULL) 74 | *p = '\x00'; 75 | 76 | /* replace work function if the original isn't allowed to run */ 77 | if (work->func != dummy && !keep_workqueue(name, work)) 78 | work->func = dummy; 79 | } 80 | -------------------------------------------------------------------------------- /host/asm.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | .code64 4 | 5 | ENTRY(vm_exit_handler) 6 | push %r15 7 | push %r14 8 | push %r13 9 | push %r12 10 | push %r11 11 | push %r10 12 | push %r9 13 | push %r8 14 | push %rdi 15 | push %rsi 16 | push %rbp 17 | push %rbp # %rsp 18 | push %rbx 19 | push %rdx 20 | push %rcx 21 | push %rax 22 | 23 | mov %rsp, %rdi 24 | call _vm_exit_handler 25 | 26 | pop %rax 27 | pop %rcx 28 | pop %rdx 29 | pop %rbx 30 | pop %rbp # %rsp 31 | pop %rbp 32 | pop %rsi 33 | pop %rdi 34 | pop %r8 35 | pop %r9 36 | pop %r10 37 | pop %r11 38 | pop %r12 39 | pop %r13 40 | pop %r14 41 | pop %r15 42 | 43 | vmresume 44 | setna %al 45 | test %al, %al 46 | 47 | call cpu_vmxerror_error 48 | 1: /* vmresume_fail */ 49 | jmp 1b 50 | END(vm_exit_handler) 51 | -------------------------------------------------------------------------------- /host/breakpoint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "common/log.h" 23 | #include "host/breakpoint.h" 24 | #include "host/symbols.h" 25 | #include "host/vcpu.h" 26 | #include "host/vmx.h" 27 | 28 | #define CALL_SIZE 5 29 | 30 | extern void guest_schedule_end_stub(void); 31 | extern void guest_schedule_tail_end_stub(void); 32 | extern void guest_do_exit_stub(void); 33 | extern void guest_prepare_binprm_stub(void); 34 | extern void process_one_work_stub(void); 35 | 36 | struct breakpoint bp_do_exit, 37 | bp_schedule_end, 38 | bp_schedule_tail_end, 39 | bp_prepare_binprm, 40 | bp_vt_console_print, 41 | bp_process_one_work; 42 | 43 | 44 | /* Breakpoint in encapsulated guest. 45 | * 46 | * Return 0 if INT3 trap must be delivered, otherwise, return 1 and emulate 47 | * hooked instruction. */ 48 | int handle_int3_hook(struct vcpu *vcpu) 49 | { 50 | unsigned long rip; 51 | 52 | rip = cpu_vmcs_readl(GUEST_RIP); 53 | 54 | if (rip == bp_do_exit.addr) { 55 | /* guest_do_exit_stub() uses rax to return in do_exit() */ 56 | vcpu->regs.rax = rip + CALL_SIZE; 57 | 58 | /* redirect execution to guest_do_exit_stub */ 59 | cpu_vmcs_writel(GUEST_RIP, (unsigned long)guest_do_exit_stub); 60 | return 1; 61 | } 62 | 63 | else if (rip == bp_prepare_binprm.addr) { 64 | /* guest_prepare_binprm_stub() uses rax to return to 65 | * prepare_binprm() */ 66 | vcpu->regs.rax = rip + CALL_SIZE; 67 | 68 | /* redirect execution to guest_prepare_binprm_stub */ 69 | cpu_vmcs_writel(GUEST_RIP, (unsigned long)guest_prepare_binprm_stub); 70 | return 1; 71 | } 72 | 73 | else if (rip == bp_schedule_end.addr) { 74 | /* redirect execution to guest_schedule_end_stub */ 75 | cpu_vmcs_writel(GUEST_RIP, (unsigned long)guest_schedule_end_stub); 76 | return 1; 77 | } 78 | 79 | else if (rip == bp_schedule_tail_end.addr) { 80 | /* redirect execution to guest_schedule_tail_end_stub */ 81 | cpu_vmcs_writel(GUEST_RIP, (unsigned long)guest_schedule_tail_end_stub); 82 | return 1; 83 | } 84 | 85 | else if (rip == bp_vt_console_print.addr) { 86 | cappsule_dmesg(vcpu->capsule, vcpu->regs.rsi, vcpu->regs.rdx); 87 | 88 | cpu_vmcs_writel(GUEST_RIP, rip + CALL_SIZE); 89 | return 1; 90 | } 91 | 92 | else if (rip == bp_process_one_work.addr) { 93 | vcpu->regs.rax = rip + CALL_SIZE; 94 | cpu_vmcs_writel(GUEST_RIP, (unsigned long)process_one_work_stub); 95 | return 1; 96 | } 97 | 98 | else { 99 | return 0; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /host/process.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "host/process.h" 27 | #include "host/snapshot.h" 28 | #include "host/symbols.h" 29 | 30 | 31 | static const char *kthreads_comm[] = { 32 | "kdevtmpfs", 33 | "kthreadd", 34 | "watchdog", 35 | "rcu_sched", 36 | "ksoftirqd", 37 | "migration", /* stop_cpus(), called by jump labels */ 38 | "rcuob", 39 | "rcuos", 40 | "rcu_bh", 41 | "rcu_sched", 42 | NULL 43 | }; 44 | 45 | 46 | static int keep_kthread(struct task_struct *task) 47 | { 48 | const char **comm; 49 | char *p; 50 | 51 | for (comm = kthreads_comm; *comm != NULL; comm++) { 52 | p = strchr(task->comm, '/'); 53 | if (p == NULL) { 54 | if (strcmp(*comm, task->comm) == 0) 55 | return 1; 56 | } else { 57 | if (strncmp(*comm, task->comm, p - task->comm) == 0) 58 | return 1; 59 | } 60 | } 61 | 62 | return 0; 63 | } 64 | 65 | static int keep_worker(struct task_struct *task) 66 | { 67 | /* Allow every kworker to be scheduled in the capsule, because kworker's 68 | * functions are filtered. It's not generic, and requires a whitelist of 69 | * workqueue functions allowed to be executed. */ 70 | return 1; 71 | 72 | /* A better solution requires kworkers to be frozen 73 | * (freeze_workqueues_begin + freeze_workqueues_busy) before snapshot, 74 | * and restarted during capsule's init (thaw_workqueues). Each workqueue 75 | * can be filtered before being restarted. Nevertheless it doesn't work 76 | * because some workqueues are not freezable 77 | * (!(wq->flags & WQ_FREEZABLE)). */ 78 | } 79 | 80 | int keep_userland_process(struct task_struct *task) 81 | { 82 | int i; 83 | 84 | for (i = 0; i < ARRAY_SIZE(snapshot.process.allowed_pids.pids); i++) { 85 | if (snapshot.process.allowed_pids.pids[i] == task->pid) 86 | return 1; 87 | } 88 | 89 | return 0; 90 | } 91 | 92 | /* When snapshot is created, a bitmap is initialized with: 93 | * - 0: process is allowed to run (fsclient, X, etc.), 94 | * - 1: process is not allowed to run. 95 | * 96 | * During execution, capsules check this bitmap to know if a process is allowed 97 | * to run. It's not necessary to update bitmap when a process is created or 98 | * exits. Only processes allowed to run can call exit(), and a new process 99 | * already have its bit set to 0 (because its pid is necessarily different than 100 | * pid of an uninterruptible process). */ 101 | err_t create_process_bitmap(struct task_struct *task) 102 | { 103 | struct task_struct *g, *p; 104 | size_t bitmap_size; 105 | void *pid_bitmap; 106 | pid_t max_pid; 107 | 108 | /* tasklist_lock should be held to iterate through each thread, but 109 | * it's not the case (because tasklist_lock is not exported). This 110 | * shouldn't be an issue because only one CPU is online during snapshot 111 | * and we're in VMX-root mode (thus IRQs are disabled). */ 112 | 113 | max_pid = 0; 114 | do_each_thread(g, p) { 115 | if (p->pid > max_pid) 116 | max_pid = p->pid; 117 | } while_each_thread(g, p); 118 | 119 | max_pid++; 120 | bitmap_size = max_pid / BITS_PER_BYTE; 121 | if (max_pid % BITS_PER_BYTE != 0) 122 | bitmap_size++; 123 | 124 | pid_bitmap = kzalloc(bitmap_size, GFP_ATOMIC); 125 | if (pid_bitmap == NULL) 126 | return ERROR_SNAP_PID_BITMAP_ALLOC_FAILED; 127 | 128 | do_each_thread(g, p) { 129 | /* Allow capsule_task->parent (fake /sbin/init of virtexec) and 130 | * capsule_task (its child) to run. If /sbin/init can't run, 131 | * exited children stay in zombie state in capsule. 132 | * 133 | * XXX: /sbin/init is not chrooted. It doesn't seem to be 134 | * problematic because no files are open. */ 135 | if (p == task || p == task->parent) { 136 | //hv_dbg("%s: %d %s", __func__, p->pid, p->comm); 137 | continue; 138 | } 139 | 140 | /* is_idle_task(p) */ 141 | if (p->pid == 0) { 142 | continue; 143 | } else if (p->flags & PF_WQ_WORKER) { 144 | if (keep_worker(p)) 145 | continue; 146 | } else if (p->flags & PF_KTHREAD) { 147 | if (keep_kthread(p)) 148 | continue; 149 | } else if (keep_userland_process(p)) { 150 | continue; 151 | } 152 | 153 | set_bit(p->pid, pid_bitmap); 154 | } while_each_thread(g, p); 155 | 156 | snapshot.process.max_pid = max_pid; 157 | snapshot.process.pid_bitmap = pid_bitmap; 158 | snapshot.process.capsule_task = task; 159 | 160 | return SUCCESS; 161 | } 162 | 163 | void free_process_bitmap(void) 164 | { 165 | kfree(snapshot.process.pid_bitmap); 166 | snapshot.process.pid_bitmap = NULL; 167 | } 168 | -------------------------------------------------------------------------------- /host/symbols.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "common/log.h" 22 | #include "common/error.h" 23 | #include "host/symbols.h" 24 | 25 | struct mm_struct *_init_mm; 26 | struct list_head *_nosave_regions; 27 | struct mutex *_uevent_sock_mutex; 28 | int (*_is_vmalloc_or_module_addr)(const void *addr); 29 | struct pglist_data *(*_first_online_pgdat)(void); 30 | struct zone *(*_next_zone)(struct zone *zone); 31 | int (*_pfn_is_nosave)(unsigned long); 32 | unsigned long (*_shrink_all_memory)(unsigned long nr_pages); 33 | void (*_native_safe_halt)(void); 34 | void (*_vt_console_print)(void); 35 | int (*_walk_page_range)(unsigned long addr, unsigned long end, 36 | struct mm_walk *walk); 37 | void (*_schedule_tail)(struct task_struct *prev); 38 | int (*_sys_execve)(const char *filename, const char * const*__argv, 39 | const char * const*__envp); 40 | void (*_process_one_work)(struct worker *worker, struct work_struct *work); 41 | 42 | struct symbol symbols[] = { 43 | SYMBOL(init_mm), 44 | SYMBOL(nosave_regions), 45 | SYMBOL(uevent_sock_mutex), 46 | SYMBOL(is_vmalloc_or_module_addr), 47 | SYMBOL(first_online_pgdat), 48 | SYMBOL(next_zone), 49 | SYMBOL(pfn_is_nosave), 50 | SYMBOL(shrink_all_memory), 51 | SYMBOL(native_safe_halt), 52 | SYMBOL(vt_console_print), 53 | SYMBOL(walk_page_range), 54 | SYMBOL(schedule_tail), 55 | SYMBOL(sys_execve), 56 | SYMBOL(process_one_work), 57 | { NULL, NULL } 58 | }; 59 | 60 | struct per_cpu_symbol per_cpu_symbols[] = { 61 | { NULL, NULL } 62 | }; 63 | -------------------------------------------------------------------------------- /host/time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "shadow_process.h" 24 | #include "common/time.h" 25 | #include "host/capsule.h" 26 | #include "host/interrupt.h" 27 | #include "host/time.h" 28 | 29 | #define TSC_DIVISOR 32 30 | 31 | 32 | enum hrtimer_restart capsule_clock_event_function(struct capsule *capsule) 33 | { 34 | struct capsule *running_capsule; 35 | 36 | running_capsule = current_capsule(capsule->vcpu); 37 | 38 | atomic_set(&capsule->shadowp->timer_set, 0); 39 | 40 | if (capsule->id == running_capsule->id) { 41 | /* Nothing to do: a LOCAL_TIMER_VECTOR interrupt was received 42 | * and the external interrupt VM-exit is ongoing. 43 | * This function is called by the interrupt handler, and the 44 | * interrupt is gone to be injected into guest. */ 45 | } else { 46 | /* The current guest is not the capsule which received the clock 47 | * event. */ 48 | add_pending_intr(capsule, LOCAL_TIMER_VECTOR, 0); 49 | tasklet_schedule(&capsule->shadowp->tasklet); 50 | } 51 | 52 | return HRTIMER_NORESTART; 53 | } 54 | 55 | static void set_timer(struct vcpu *vcpu, __u64 nsec) 56 | { 57 | struct capsule *capsule; 58 | ktime_t expires, now, t; 59 | 60 | now = ktime_get_real(); 61 | expires = ktime_add_ns(now, nsec); 62 | if (ktime_compare(expires, now) <= 0) 63 | return; 64 | 65 | /* don't cancel current timer if it is scheduled before the new one */ 66 | capsule = current_capsule(vcpu); 67 | if (atomic_read(&capsule->shadowp->timer_set)) { 68 | t = hrtimer_get_remaining(&capsule->clock_timer); 69 | t = ktime_add(now, t); 70 | if (ktime_compare(expires, t) >= 0) 71 | return; 72 | } else { 73 | atomic_set(&capsule->shadowp->timer_set, 1); 74 | } 75 | 76 | hrtimer_start(&capsule->clock_timer, expires, HRTIMER_MODE_ABS); 77 | } 78 | 79 | void vmcall_set_timer(struct vcpu *vcpu, __u64 nsec) 80 | { 81 | set_timer(vcpu, nsec); 82 | } 83 | 84 | void capsule_tsc_deadline(struct vcpu *vcpu, __u64 value) 85 | { 86 | unsigned long cycles; 87 | __u64 tsc, nsec; 88 | 89 | rdtscll(tsc); 90 | if (tsc >= value) 91 | return; 92 | 93 | cycles = (value - tsc) / TSC_DIVISOR; 94 | nsec = cycles * (1000000 / cpu_khz); 95 | 96 | set_timer(vcpu, nsec); 97 | } 98 | 99 | void init_clock_timer(struct capsule *capsule) 100 | { 101 | hrtimer_init(&capsule->clock_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS); 102 | capsule->clock_timer.function = clock_event_function; 103 | } 104 | -------------------------------------------------------------------------------- /host/transition.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "host/capsule.h" 23 | #include "host/transition.h" 24 | #include "host/vmx.h" 25 | 26 | 27 | void shadow_process_fpu_used(void); 28 | 29 | /* force capsule to #NM on FPU usage */ 30 | static void trap_on_fpu_usage(struct capsule *capsule) 31 | { 32 | unsigned long read_shadow; 33 | int host_owned; 34 | __u64 tmpl; 35 | __u32 tmp; 36 | 37 | capsule->fpu_used = 0; 38 | 39 | /* any modification of CR0.TS causes a VM-exit */ 40 | tmpl = cpu_vmcs_readl(CR0_GUEST_HOST_MASK); 41 | host_owned = tmpl & X86_CR0_TS; 42 | if (!host_owned) { 43 | tmpl |= X86_CR0_TS; 44 | cpu_vmcs_writel(CR0_GUEST_HOST_MASK, tmpl); 45 | } 46 | 47 | /* any #NM causes a VM-exit */ 48 | tmp = cpu_vmcs_read32(EXCEPTION_BITMAP); 49 | tmp |= (1 << X86_TRAP_NM); 50 | cpu_vmcs_write32(EXCEPTION_BITMAP, tmp); 51 | 52 | /* if CR0 guest host mask wasn't in use, set CR0 read shadow to the 53 | * guest value */ 54 | tmpl = cpu_vmcs_readl(GUEST_CR0); 55 | if (!host_owned) { 56 | read_shadow = cpu_vmcs_readl(CR0_READ_SHADOW); 57 | if ((read_shadow & X86_CR0_TS) != (tmpl & X86_CR0_TS)) { 58 | if (read_shadow & X86_CR0_TS) 59 | read_shadow &= ~X86_CR0_TS; 60 | else 61 | read_shadow |= X86_CR0_TS; 62 | cpu_vmcs_writel(CR0_READ_SHADOW, read_shadow); 63 | } 64 | } 65 | 66 | /* set guest CR0.TS (guest reads value from read shadow) to force #NM */ 67 | if (!(tmpl & X86_CR0_TS)) { 68 | tmpl |= X86_CR0_TS; 69 | cpu_vmcs_writel(GUEST_CR0, tmpl); 70 | } 71 | } 72 | 73 | /* switch from trusted guest to capsule, not from capsule to capsule */ 74 | err_t load_capsule_vmcs(struct vcpu *vcpu, struct capsule *capsule) 75 | { 76 | __u32 tmp; 77 | 78 | //tg_dbg("%s (cpu=%d)", __func__, smp_processor_id()); 79 | 80 | ASSERT(vcpu == capsule->vcpu); 81 | 82 | if (cpu_vmcs_load(capsule->vmcs) != 0) 83 | return ERROR_LOAD_CAPSULE_VMCS; 84 | 85 | /* if pending interrupts, enable interrupt-window exiting */ 86 | tmp = cpu_vmcs_read32(CPU_BASED_VM_EXEC_CONTROL); 87 | if (intr_pending(capsule)) 88 | tmp |= CPU_BASED_VIRTUAL_INTR_PENDING; 89 | else 90 | tmp &= ~CPU_BASED_VIRTUAL_INTR_PENDING; 91 | cpu_vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, tmp); 92 | 93 | trap_on_fpu_usage(capsule); 94 | 95 | vcpu->guest = GUEST_CAPSULE; 96 | vcpu->capsule = capsule; 97 | 98 | return SUCCESS; 99 | } 100 | 101 | err_t load_trusted_vmcs(struct vcpu *vcpu) 102 | { 103 | //cpsl_dbg(vcpu->capsule->id, "%s (cpu=%d)", 104 | // __func__, smp_processor_id()); 105 | 106 | ASSERT(vcpu->cpu == smp_processor_id()); 107 | 108 | if (cpu_vmcs_load(vcpu->vmcs_trusted) != 0) 109 | return ERROR_LOAD_TRUSTED_VMCS; 110 | 111 | vcpu->guest = GUEST_TRUSTED; 112 | vcpu->capsule = NULL; 113 | 114 | return SUCCESS; 115 | } 116 | 117 | /* called from host */ 118 | void switch_to_capsule(struct vcpu *vcpu, struct capsule *capsule) 119 | { 120 | struct regs regs; 121 | 122 | if (capsule->flags & CPSL_EXITED) { 123 | /* The capsule has already exited (but decapsulate has not been 124 | * called). It should not try to schedule to capsule. */ 125 | tg_info("%s: capsule has exited", __func__); 126 | return; 127 | } 128 | 129 | capsule->stats.nr_switches++; 130 | capsule->last_schedule = ktime_get(); 131 | 132 | save_context(&vcpu->trusted_ctx, &vcpu->regs); 133 | restore_context(&capsule->ctx, ®s); 134 | 135 | if (load_capsule_vmcs(vcpu, capsule) != SUCCESS) 136 | kill_s(capsule, KILL_SWITCH_VM_TO_CAPSULE); 137 | 138 | cpu_vmx_resume(®s); 139 | } 140 | 141 | /* Force shadow process to execute a FPU instruction. Since a capsule is 142 | * assigned to a shadow process: 143 | * - we assume that the shadow process doesn't use FPU registers, 144 | * - trusted guest kernel will save capsule FPU registers if shadow process is 145 | * forced to execute one FPU instruction (fnop). 146 | * 147 | * Current vmcs must be the one from trusted guest */ 148 | void force_shadow_process_fpu_usage(void) 149 | { 150 | unsigned long rsp; 151 | 152 | /* fake call to shadow_process_fpu_used (writes to trusted guest 153 | * memory) */ 154 | rsp = cpu_vmcs_readl(GUEST_RSP); 155 | rsp -= sizeof(unsigned long); 156 | *(unsigned long *)rsp = cpu_vmcs_readl(GUEST_RIP); 157 | cpu_vmcs_writel(GUEST_RSP, rsp); 158 | cpu_vmcs_writel(GUEST_RIP, (long)&shadow_process_fpu_used); 159 | } 160 | 161 | /* called from host */ 162 | void switch_to_trusted(struct vcpu *vcpu) 163 | { 164 | struct capsule *capsule; 165 | struct task_struct *tsk; 166 | struct regs regs; 167 | ktime_t now; 168 | 169 | capsule = current_capsule(vcpu); 170 | tsk = get_current(); 171 | 172 | now = ktime_get(); 173 | timespec_add_ns(&capsule->stats.total_elapsed_time, 174 | ktime_to_ns(ktime_sub(now, capsule->last_schedule))); 175 | 176 | save_context(&capsule->ctx, &vcpu->regs); 177 | restore_context(&vcpu->trusted_ctx, ®s); 178 | 179 | if (load_trusted_vmcs(vcpu) != SUCCESS) 180 | panic("failed to load trusted vmcs"); 181 | 182 | if (capsule->fpu_used) { 183 | force_shadow_process_fpu_usage(); 184 | capsule->fpu_used = 0; 185 | } 186 | 187 | cpu_vmx_resume(®s); 188 | } 189 | -------------------------------------------------------------------------------- /host/vmx_instr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "host/capsule.h" 21 | #include "host/vmx.h" 22 | 23 | 24 | noinline void cpu_vmxerror_error(void) 25 | { 26 | __u32 vm_instr_error; 27 | vm_instr_error = cpu_vmcs_read32(VM_INSTRUCTION_ERROR); 28 | printk(KERN_ERR "[virt] vmresume error (err %d)\n", vm_instr_error); 29 | dump_stack(); 30 | } 31 | 32 | noinline void cpu_vmwrite_error(unsigned long field, unsigned long value) 33 | { 34 | printk(KERN_ERR "[virt] vmwrite error: reg %lx value %lx (err %d)\n", 35 | field, value, cpu_vmcs_read32(VM_INSTRUCTION_ERROR)); 36 | dump_stack(); 37 | } 38 | 39 | /* all general purpose registers except RIP and RSP are invalid */ 40 | noinline void cpu_vmresume_failed(void) 41 | { 42 | struct capsule *capsule; 43 | __u32 vm_instr_error; 44 | struct vcpu *vcpu; 45 | unsigned int cpu; 46 | 47 | cpu = smp_processor_id(); 48 | vcpu = &vmm.vcpus[cpu]; 49 | 50 | vm_instr_error = cpu_vmcs_read32(VM_INSTRUCTION_ERROR); 51 | 52 | if (vcpu->guest == GUEST_TRUSTED) { 53 | panic("vmresume failed (error: %d)", vm_instr_error); 54 | } else { 55 | capsule = current_capsule(vcpu); 56 | cpsl_err(capsule->id, "vmresume failed (error: %d)", 57 | vm_instr_error); 58 | kill(vcpu, KILL_VMRESUME_FAILED); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /host/xchan.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | #include "common/log.h" 31 | #include "common/memory.h" 32 | #include "common/params.h" 33 | #include "common/xchan.h" 34 | #include "host/capsule.h" 35 | #include "host/ept.h" 36 | #include "host/interrupt.h" 37 | #include "host/vmm.h" 38 | #include "host/vmx.h" 39 | #include "host/xchan.h" 40 | 41 | 42 | int xchan_notify_trusted(struct vcpu *vcpu, unsigned long arg0) 43 | { 44 | enum xchan_type xchan_type; 45 | struct eventfd_ctx *event; 46 | struct capsule *capsule; 47 | 48 | xchan_type = arg0; 49 | if (xchan_type < 0 || xchan_type >= XCHAN_TYPE_MAX) 50 | return -EINVAL; 51 | 52 | capsule = current_capsule(vcpu); 53 | 54 | /* XXX: needs lock? */ 55 | event = capsule->xchan.events[xchan_type]; 56 | 57 | /* event is NULL if device in trusted guest doesn't have its xchan 58 | * yet */ 59 | if (event == NULL) { 60 | hv_dbg("%s: event is NULL (%d)", __func__, xchan_type); 61 | return -EINVAL; 62 | } 63 | 64 | eventfd_signal(event, 1); 65 | 66 | return 0; 67 | } 68 | 69 | int xchan_set_event(unsigned int id, unsigned long arg1, struct eventfd_ctx *event) 70 | { 71 | enum xchan_type xchan_type; 72 | struct capsule *capsule; 73 | int ret; 74 | 75 | xchan_type = arg1; 76 | if (xchan_type < 0 || xchan_type >= XCHAN_TYPE_MAX) 77 | return -EINVAL; 78 | 79 | capsule = get_capsule_from_id(id); 80 | if (capsule == NULL) { 81 | hv_info("xchan failed to set event (invalid id %d)", id); 82 | return -EINVAL; 83 | } 84 | 85 | if (capsule->xchan.events[xchan_type] == NULL) { 86 | capsule->xchan.events[xchan_type] = event; 87 | ret = capsule->vcpu->cpu; 88 | } else { 89 | hv_info("xchan failed to set event (already set, id: %d)", id); 90 | ret = -EINVAL; 91 | } 92 | 93 | put_capsule(capsule); 94 | 95 | return ret; 96 | } 97 | 98 | void xchan_map_guest_page(struct vcpu *vcpu, unsigned long gpa, unsigned int n) 99 | { 100 | struct capsule *capsule; 101 | unsigned long hpa; 102 | int err; 103 | 104 | capsule = current_capsule(vcpu); 105 | if (n >= XCHAN_NPAGES_TOTAL) 106 | kill_s(capsule, KILL_XCHAN_MAP_INVALID_INDEX); 107 | 108 | remove_ept_translation(capsule, gpa); 109 | 110 | hpa = __pa(capsule->params->xchan_pages + n * PAGE_SIZE); 111 | err = install_ept_translation(capsule, gpa, hpa, EPT_PROT_RW); 112 | if (err != 0) 113 | kill_s(capsule, KILL_XCHAN_MAP_PAGES); 114 | 115 | /* XXX: INVEPT_SINGLE_CONTEXT doesn't work */ 116 | invept(INVEPT_ALL_CONTEXT, 0); 117 | } 118 | 119 | void xchan_guest_closed(struct vcpu *vcpu, unsigned long arg0) 120 | { 121 | struct capsule *capsule; 122 | kill_t reason; 123 | 124 | capsule = current_capsule(vcpu); 125 | 126 | switch (arg0) { 127 | case XCHAN_NET: reason = KILL_XCHAN_CLOSED_NET; break; 128 | case XCHAN_GUI: reason = KILL_XCHAN_CLOSED_GUI; break; 129 | case XCHAN_FS: reason = KILL_XCHAN_CLOSED_FS; break; 130 | case XCHAN_CONSOLE: reason = KILL_XCHAN_CLOSED_CONSOLE; break; 131 | default: reason = KILL_XCHAN_CLOSED_INVALID; break; 132 | } 133 | 134 | kill_s(capsule, reason); 135 | } 136 | -------------------------------------------------------------------------------- /include/common/bluepill.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef BLUEPILL_H 18 | #define BLUEPILL_H 19 | 20 | #include "common/error.h" 21 | 22 | struct vcpu; 23 | 24 | void cpu_stop_vmm(void *arg); 25 | void cpu_exit_bluepill(struct vcpu *vcpu); 26 | err_t bluepill(void); 27 | 28 | static void inline cpu_trigger_vm_exit(void *arg) 29 | { 30 | cpuid_eax(0); 31 | } 32 | 33 | #endif /* BLUEPILL_H */ 34 | -------------------------------------------------------------------------------- /include/common/channel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_CHANNEL_H 18 | #define COMMON_CHANNEL_H 19 | 20 | long common_channel_ioctl(struct file *file, unsigned int cmd, 21 | unsigned long arg); 22 | 23 | #endif /* COMMON_CHANNEL_H */ 24 | -------------------------------------------------------------------------------- /include/common/cr4.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_CR4_H 18 | #define COMMON_CR4_H 19 | 20 | #include 21 | #include 22 | 23 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) 24 | /* Set in this cpu's CR4. */ 25 | static inline void cr4_set_bits(unsigned long mask) 26 | { 27 | unsigned long cr4; 28 | 29 | cr4 = read_cr4(); 30 | if ((cr4 | mask) != cr4) { 31 | cr4 |= mask; 32 | write_cr4(cr4); 33 | } 34 | } 35 | 36 | /* Clear in this cpu's CR4. */ 37 | static inline void cr4_clear_bits(unsigned long mask) 38 | { 39 | unsigned long cr4; 40 | 41 | cr4 = read_cr4(); 42 | if ((cr4 & ~mask) != cr4) { 43 | cr4 &= ~mask; 44 | write_cr4(cr4); 45 | } 46 | } 47 | #endif 48 | 49 | #endif /* COMMON_CR4_H */ 50 | -------------------------------------------------------------------------------- /include/common/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_ERROR_H 18 | #define COMMON_ERROR_H 19 | 20 | #include "cuapi/error.h" 21 | 22 | /* SUCCESS and err_t aren't directly declared in cuapi/error.h to allow userland 23 | * to define a similar but different enum */ 24 | #define SUCCESS HV_SUCCESS 25 | typedef enum hv_error err_t; 26 | 27 | #endif /* COMMON_ERROR_H */ 28 | -------------------------------------------------------------------------------- /include/common/exec_policy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef EXEC_POLICY_H 18 | #define EXEC_POLICY_H 19 | 20 | #include "cuapi/common/exec_policy.h" 21 | 22 | void free_exec_policies(struct exec_policies *policies); 23 | struct exec_policies *copy_exec_policies(char __user *buf, size_t size); 24 | struct exec_policies *get_exec_policies(void); 25 | void set_exec_policies(struct exec_policies *p); 26 | 27 | #endif /* EXEC_POLICY_H */ 28 | -------------------------------------------------------------------------------- /include/common/locks.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_LOCKS_H 18 | #define COMMON_LOCKS_H 19 | 20 | #include 21 | 22 | #include "common/symbols.h" 23 | 24 | static __always_inline void release_locks_after_snapshot(void) 25 | { 26 | mutex_unlock(_uevent_sock_mutex); 27 | mutex_unlock(&module_mutex); 28 | } 29 | 30 | #endif /* COMMON_LOCKS_H */ 31 | -------------------------------------------------------------------------------- /include/common/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_LOG_H 18 | #define COMMON_LOG_H 19 | 20 | #include "cuapi/log.h" 21 | #include "common/error.h" 22 | 23 | struct capsule; 24 | void cappsule_dmesg(struct capsule *capsule, unsigned long addr, size_t count); 25 | err_t log_init(void); 26 | void log_exit(void); 27 | void cpsl_log(enum CPSL_LOG_FACILIY facility, 28 | enum CPSL_LOG_LEVEL level, 29 | unsigned int id, 30 | const char *fmt, 31 | ...); 32 | 33 | #if 1 34 | #ifndef RELEASE 35 | #define cpsl_log_(facility, level, id, fmt, ...) \ 36 | cpsl_log(facility, level, id, fmt, ##__VA_ARGS__) 37 | #else 38 | #define cpsl_log_(facility, level, id, fmt, ...) do { \ 39 | if (level != CPSL_DEBUG) \ 40 | cpsl_log(facility, level, id, fmt, ##__VA_ARGS__); \ 41 | } while (0) 42 | #endif 43 | #else 44 | #define cpsl_log_(facility, level, id, fmt, ...) printk(KERN_ERR fmt "\n", ##__VA_ARGS__) 45 | #endif 46 | 47 | #define hv_err(fmt, ...) cpsl_log_(LOG_HV, CPSL_ERR, 0, fmt, ##__VA_ARGS__) 48 | #define hv_warn(fmt, ...) cpsl_log_(LOG_HV, CPSL_WARN, 0, fmt, ##__VA_ARGS__) 49 | #define hv_info(fmt, ...) cpsl_log_(LOG_HV, CPSL_INFO, 0, fmt, ##__VA_ARGS__) 50 | #define hv_dbg(fmt, ...) cpsl_log_(LOG_HV, CPSL_DEBUG, 0, fmt, ##__VA_ARGS__) 51 | 52 | #define tg_err(fmt, ...) cpsl_log_(LOG_TG, CPSL_ERR, 0, fmt, ##__VA_ARGS__) 53 | #define tg_warn(fmt, ...) cpsl_log_(LOG_TG, CPSL_WARN, 0, fmt, ##__VA_ARGS__) 54 | #define tg_info(fmt, ...) cpsl_log_(LOG_TG, CPSL_INFO, 0, fmt, ##__VA_ARGS__) 55 | #define tg_dbg(fmt, ...) cpsl_log_(LOG_TG, CPSL_DEBUG, 0, fmt, ##__VA_ARGS__) 56 | 57 | #define cpsl_err(id, fmt, ...) cpsl_log_(LOG_CPSL, CPSL_ERR, id, fmt, ##__VA_ARGS__) 58 | #define cpsl_warn(id, fmt, ...) cpsl_log_(LOG_CPSL, CPSL_WARN, id, fmt, ##__VA_ARGS__) 59 | #define cpsl_info(id, fmt, ...) cpsl_log_(LOG_CPSL, CPSL_INFO, id, fmt, ##__VA_ARGS__) 60 | #define cpsl_dbg(id, fmt, ...) cpsl_log_(LOG_CPSL, CPSL_DEBUG, id, fmt, ##__VA_ARGS__) 61 | #define cpsl_dmesg(id, fmt, ...) cpsl_log_(LOG_CPSL, CPSL_DMESG, id, fmt, ##__VA_ARGS__) 62 | 63 | #endif /* COMMON_LOG_H */ 64 | -------------------------------------------------------------------------------- /include/common/memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _COMMON_MEMORY_H 18 | #define _COMMON_MEMORY_H 19 | 20 | #include 21 | 22 | 23 | static inline void poison(void *addr, int c, size_t size) 24 | { 25 | if (addr != NULL) 26 | memset(addr, c, size); 27 | } 28 | 29 | /** 30 | * Get PFN of user virtual address. 31 | * This function is declared in a header file because it's used by guest and 32 | * host. 33 | * 34 | * @return zero on error, -1 otherwise 35 | */ 36 | static inline unsigned long uaddr_pfn(unsigned long cr3, unsigned long uaddr) 37 | { 38 | unsigned long pfn; 39 | pgd_t *pgd; 40 | pud_t *pud; 41 | pmd_t *pmd; 42 | pte_t *pte; 43 | 44 | pgd = (pgd_t *)__va(cr3 & PHYSICAL_PAGE_MASK) + pgd_index(uaddr); 45 | if (pgd_none(*pgd)) 46 | return 0; 47 | 48 | pud = pud_offset(pgd, uaddr); 49 | if (pud_none(*pud)) 50 | return 0; 51 | 52 | if (pud_large(*pud)) { 53 | pte = (pte_t *)pud; 54 | if (!pte_present(*pte)) 55 | return 0; 56 | 57 | pfn = pte_pfn(*pte) + ((uaddr & ~PUD_MASK) >> PAGE_SHIFT); 58 | return pfn; 59 | } 60 | 61 | pmd = pmd_offset(pud, uaddr); 62 | if (pmd_none(*pmd)) 63 | return 0; 64 | 65 | if (pmd_large(*pmd)) { 66 | pte = (pte_t *)pmd; 67 | if (!pte_present(*pte)) 68 | return 0; 69 | 70 | pfn = pte_pfn(*pte) + ((uaddr & ~PMD_MASK) >> PAGE_SHIFT); 71 | return pfn; 72 | } 73 | 74 | pte = pte_offset_kernel(pmd, uaddr); 75 | 76 | if (pte_present(*pte)) 77 | return pte_pfn(*pte); 78 | 79 | return 0; 80 | } 81 | 82 | 83 | #endif /* _COMMON_MEMORY_H */ 84 | -------------------------------------------------------------------------------- /include/common/mfn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_MFN_H 18 | #define COMMON_MFN_H 19 | 20 | struct vmcall_gpa_hva_convert { 21 | unsigned int capsule_id; 22 | uid_t xorg_uid; 23 | unsigned int num_mfn; 24 | unsigned long *gpa; /* gpa array is given by trusted guest */ 25 | unsigned long *res_hva; /* hva array is filled by host */ 26 | }; 27 | 28 | #endif /* COMMON_MFN_H */ 29 | -------------------------------------------------------------------------------- /include/common/params.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_PARAMS_H 18 | #define COMMON_PARAMS_H 19 | 20 | #include 21 | 22 | #include "cuapi/common/uuid.h" 23 | 24 | struct daemon; 25 | 26 | struct capsule_params { 27 | struct uuid policy_uuid; 28 | bool no_gui; 29 | struct winsize tty_size; 30 | unsigned int memory_limit; 31 | void *info_pages; 32 | unsigned long xchan_pages; 33 | uid_t uid; 34 | 35 | /* only use by shadow process */ 36 | struct daemon *daemon; 37 | }; 38 | 39 | #endif /* COMMON_PARAMS_H */ 40 | -------------------------------------------------------------------------------- /include/common/shared_mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_SHARED_MEM_H 18 | #define COMMON_SHARED_MEM_H 19 | 20 | #include 21 | 22 | #include "common/exec_policy.h" 23 | #include "common/snapshot_process.h" 24 | #include "cuapi/common/uuid.h" 25 | 26 | 27 | struct shared_mem { 28 | unsigned long blocked_intr_bitmap[256 / BITS_PER_LONG]; 29 | struct winsize tty_size; 30 | 31 | /* The following variables are set by host during capsule 32 | * initialization, but host never relies on them. It doesn't matter if 33 | * guest modifies them. Ideally, these variables should be mapped in a 34 | * read-only page. */ 35 | 36 | /* These informations are specific to each capsule. */ 37 | unsigned int capsule_id; 38 | struct uuid policy_uuid; 39 | bool no_gui; 40 | 41 | /* These informations are common to each capsule. */ 42 | __u8 xchan_first_vector; 43 | struct snapshot_process process; 44 | struct exec_policies *exec_policies; 45 | }; 46 | 47 | #endif /* COMMON_SHARED_MEM_H */ 48 | -------------------------------------------------------------------------------- /include/common/snapshot_process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_SNAPSHOT_PROCESS_H 18 | #define COMMON_SNAPSHOT_PROCESS_H 19 | 20 | #include "cuapi/common/process.h" 21 | 22 | struct task_struct; 23 | 24 | /* informations related to the processes during snapshot */ 25 | struct snapshot_process { 26 | struct task_struct *capsule_task; 27 | struct allowed_pids allowed_pids; 28 | pid_t max_pid; 29 | void *pid_bitmap; 30 | }; 31 | 32 | #endif /* COMMON_SNAPSHOT_PROCESS_H */ 33 | -------------------------------------------------------------------------------- /include/common/symbols.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_SYMBOLS_H 18 | #define COMMON_SYMBOLS_H 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "common/error.h" 26 | #include "common/log.h" 27 | 28 | #define SYMBOL(name) { #name, (unsigned long *)&_##name } 29 | #define PER_CPU_SYMBOL(name) { #name, (unsigned long *)_##name } 30 | 31 | /* this symbol is resolved by hypervisor and guest */ 32 | extern struct mutex *_uevent_sock_mutex; 33 | 34 | struct symbol { 35 | char *name; 36 | unsigned long *addr; 37 | }; 38 | 39 | struct per_cpu_symbol { 40 | char *name; 41 | unsigned long *addr; /* [NR_CPUS] */ 42 | }; 43 | 44 | static inline err_t resolve_symbols(struct symbol *symbols) 45 | { 46 | char *name; 47 | int i; 48 | 49 | for (i = 0; symbols[i].name != NULL; i++) { 50 | name = symbols[i].name; 51 | *symbols[i].addr = (unsigned long)kallsyms_lookup_name(name); 52 | if (*symbols[i].addr == 0) { 53 | printk(KERN_ERR "can't resolve %s\n", name); 54 | return ERROR_SYMBOL_RESOLUTION; 55 | } 56 | } 57 | 58 | return SUCCESS; 59 | } 60 | 61 | static inline err_t resolve_per_cpu_symbols(struct per_cpu_symbol *per_cpu_symbols) 62 | { 63 | unsigned long addr, *offsets; 64 | int cpu, i; 65 | 66 | /* don't overflow frame size, use kmalloc() */ 67 | offsets = kmalloc_array(NR_CPUS, sizeof(unsigned long), GFP_KERNEL); 68 | if (offsets == NULL) 69 | return -1; 70 | 71 | for_each_possible_cpu(cpu) 72 | offsets[cpu] = __per_cpu_offset[cpu]; 73 | 74 | for (i = 0; per_cpu_symbols[i].name != NULL; i++) { 75 | addr = kallsyms_lookup_name(per_cpu_symbols[i].name); 76 | if (addr == 0) { 77 | printk(KERN_ERR "can't resolve %s", 78 | per_cpu_symbols[i].name); 79 | kfree(offsets); 80 | return ERROR_SYMBOL_RESOLUTION; 81 | } 82 | 83 | for_each_possible_cpu(cpu) 84 | per_cpu_symbols[i].addr[cpu] = offsets[cpu] + addr; 85 | } 86 | 87 | kfree(offsets); 88 | 89 | return SUCCESS; 90 | } 91 | 92 | #endif /* COMMON_SYMBOLS_H */ 93 | -------------------------------------------------------------------------------- /include/common/time.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_TIME_H 18 | #define COMMON_TIME_H 19 | 20 | #include 21 | 22 | enum hrtimer_restart clock_event_function(struct hrtimer *timer); 23 | 24 | #endif /* COMMON_TIME_H */ 25 | -------------------------------------------------------------------------------- /include/common/vmcall.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef VMCALL_H 18 | #define VMCALL_H 19 | 20 | #include "cuapi/common/vmcall.h" 21 | 22 | static __always_inline void vmcall_error(unsigned long reason, 23 | __u8 invalid, 24 | __u8 valid) 25 | { 26 | /* vmcall instruction is never called in VMX root operation. One can 27 | * know which kind of guest failed thanks to the vmcall's reason. 28 | * Unfortunately, tg_err() can't be used because it calls cpsl_log() 29 | * which isn't available in cappsule-guest.ko. */ 30 | printk(KERN_ERR "[cappsule] vmcall %ld failed (%d %d)", reason, invalid, 31 | valid); 32 | } 33 | 34 | /* use gcc calling convention to pass parameters through vmcall: 35 | * reason: rdi, args: rsi, rdx, rcx, etc. */ 36 | 37 | static __always_inline void cpu_vmcs_vmcall(unsigned long reason, 38 | unsigned long arg0) 39 | { 40 | __u8 error, vmfailinvalid, vmfailvalid; 41 | 42 | asm volatile ( 43 | /* clear ZF and CF, otherwise guest may think that vmcall 44 | * failed. encapsulated process may trick this by setting rsp to 45 | * zero, but what's the point? */ 46 | "test %%rsp, %%rsp\n" 47 | 48 | "vmcall\n" 49 | "setbe %0\n" 50 | "setb %1\n" 51 | "sete %2\n" 52 | : "=qm"(error), "=qm"(vmfailinvalid), "=qm"(vmfailvalid) 53 | : "D"(reason), "S"(arg0) : "cc", "memory" 54 | ); 55 | 56 | if (error) 57 | vmcall_error(reason, vmfailinvalid, vmfailvalid); 58 | } 59 | 60 | /* vmcall returns an value into rax */ 61 | static __always_inline long cpu_vmcs_vmcall_ret(unsigned long reason, 62 | unsigned long arg0) 63 | { 64 | __u8 error, vmfailinvalid, vmfailvalid; 65 | unsigned long ret; 66 | 67 | asm volatile ( 68 | "test %%rsp, %%rsp\n" 69 | 70 | "vmcall\n" 71 | "setbe %0\n" 72 | "setb %1\n" 73 | "sete %2\n" 74 | : "=qm"(error), "=qm"(vmfailinvalid), "=qm"(vmfailvalid), 75 | "=a"(ret) 76 | : "D"(reason), "S"(arg0) : "cc", "memory" 77 | ); 78 | 79 | if (error) { 80 | vmcall_error(reason, vmfailinvalid, vmfailvalid); 81 | ret = -1; 82 | } 83 | 84 | return ret; 85 | } 86 | 87 | static __always_inline void cpu_vmcs_vmcall3(unsigned long reason, 88 | unsigned long arg0, 89 | unsigned long arg1) 90 | { 91 | __u8 error, vmfailinvalid, vmfailvalid; 92 | 93 | asm volatile ( 94 | "test %%rsp, %%rsp\n" 95 | 96 | "vmcall\n" 97 | "setbe %0\n" 98 | "setb %1\n" 99 | "sete %2\n" 100 | : "=qm"(error), "=qm"(vmfailinvalid), "=qm"(vmfailvalid) 101 | : "D"(reason), "S"(arg0), "d"(arg1) : "cc", "memory" 102 | ); 103 | 104 | if (error) 105 | vmcall_error(reason, vmfailinvalid, vmfailvalid); 106 | } 107 | 108 | 109 | static __always_inline long cpu_vmcs_vmcall3_ret(unsigned long reason, 110 | unsigned long arg0, 111 | unsigned long arg1) 112 | { 113 | __u8 error, vmfailinvalid, vmfailvalid; 114 | unsigned long ret; 115 | 116 | asm volatile ( 117 | "test %%rsp, %%rsp\n" 118 | 119 | "vmcall\n" 120 | "setbe %0\n" 121 | "setb %1\n" 122 | "sete %2\n" 123 | : "=qm"(error), "=qm"(vmfailinvalid), "=qm"(vmfailvalid), 124 | "=a"(ret) 125 | : "D"(reason), "S"(arg0), "d"(arg1) : "cc", "memory" 126 | ); 127 | 128 | if (error) { 129 | vmcall_error(reason, vmfailinvalid, vmfailvalid); 130 | ret = -1; 131 | } 132 | 133 | return ret; 134 | } 135 | 136 | static __always_inline long cpu_vmcs_vmcall4_ret(unsigned long reason, 137 | unsigned long arg0, 138 | unsigned long arg1, 139 | unsigned long arg2) 140 | { 141 | __u8 error, vmfailinvalid, vmfailvalid; 142 | unsigned long ret; 143 | 144 | asm volatile ( 145 | "test %%rsp, %%rsp\n" 146 | 147 | "vmcall\n" 148 | "setbe %0\n" 149 | "setb %1\n" 150 | "sete %2\n" 151 | : "=qm"(error), "=qm"(vmfailinvalid), "=qm"(vmfailvalid), 152 | "=a"(ret) 153 | : "D"(reason), "S"(arg0), "d"(arg1), "c"(arg2) : "cc", "memory" 154 | ); 155 | 156 | if (error) { 157 | vmcall_error(reason, vmfailinvalid, vmfailvalid); 158 | ret = -1; 159 | } 160 | 161 | return ret; 162 | } 163 | 164 | 165 | /* store result into res1 and res2 */ 166 | static __always_inline void cpu_vmcs_vmcall2(unsigned long reason, 167 | unsigned long arg0, 168 | unsigned long *res1, 169 | unsigned long *res2) 170 | { 171 | __u8 error, vmfailinvalid, vmfailvalid; 172 | unsigned long rdx, rcx; 173 | 174 | asm volatile ( 175 | "test %%rsp, %%rsp\n" 176 | 177 | /* vmcall2 is responsible of putting result into rdx and rcx */ 178 | "vmcall\n" 179 | "setbe %0\n" 180 | "setb %1\n" 181 | "sete %2\n" 182 | : "=qm"(error), "=qm"(vmfailinvalid), "=qm"(vmfailvalid), 183 | "=d"(rdx), "=c"(rcx) 184 | : "D"(reason), "S"(arg0) 185 | : "cc", "memory" 186 | ); 187 | 188 | if (error) 189 | vmcall_error(reason, vmfailinvalid, vmfailvalid); 190 | 191 | *res1 = rdx; 192 | *res2 = rcx; 193 | } 194 | 195 | #endif /* VMCALL_H */ 196 | -------------------------------------------------------------------------------- /include/common/xchan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef COMMON_XCHAN_H 18 | #define COMMON_XCHAN_H 19 | 20 | #include 21 | #include 22 | 23 | #include "cuapi/common/xchan.h" 24 | 25 | #ifndef IRQ0_VECTOR 26 | # define IRQ0_VECTOR ((FIRST_EXTERNAL_VECTOR + 16) & ~15) 27 | # define IRQ15_VECTOR (IRQ0_VECTOR + 15) 28 | #endif 29 | 30 | struct xchan_pending_intr { 31 | unsigned int capsule_id; 32 | __u8 vector; 33 | int error; 34 | }; 35 | 36 | static inline unsigned int xchan_vector_to_irq(unsigned int vector) 37 | { 38 | return (vector - IRQ0_VECTOR) & 0xff; 39 | } 40 | 41 | void cpu_xchan_notify_guest(void *arg); 42 | 43 | #endif /* COMMON_XCHAN_H */ 44 | -------------------------------------------------------------------------------- /include/cuapi/common/exec_policy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_EXEC_POLICY_H 18 | #define CUAPI_EXEC_POLICY_H 19 | 20 | #include "cuapi/common/uuid.h" 21 | 22 | struct exec_policy { 23 | struct uuid uuid; 24 | unsigned int n; /* number of paths */ 25 | unsigned char data[]; /* unsigned int offsets[n]; 26 | * char paths[][n]; */ 27 | }; 28 | 29 | struct exec_policies { 30 | unsigned int n; /* number of policies */ 31 | unsigned int size; /* size of policies (in bytes), page size aligned */ 32 | unsigned char data[]; /* unsigned int offsets[n]; 33 | * struct exec_policy policies[n]; */ 34 | }; 35 | 36 | #endif /* CUAPI_EXEC_POLICY_H */ 37 | -------------------------------------------------------------------------------- /include/cuapi/common/kill.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_KILL_H 18 | #define CUAPI_KILL_H 19 | 20 | typedef enum { 21 | KILL_VMCALL_EXIT = 0, /* encaspulated process exited */ 22 | KILL_VMCALL_FATAL_SIGNAL, /* shadow process killed */ 23 | 24 | /* VM-exits */ 25 | KILL_MOVE_TO_CR0, 26 | KILL_MOVE_TO_CR4, 27 | KILL_MOVE_TO_CR8, 28 | KILL_MOVE_TO_CRX, 29 | 30 | KILL_CLTS, 31 | 32 | KILL_MOVE_FROM_CR0_BUG, 33 | KILL_MOVE_FROM_CR4_BUG, 34 | KILL_MOVE_FROM_CR8, 35 | KILL_MOVE_FROM_CRX, 36 | 37 | KILL_LMSW_TODO, 38 | 39 | KILL_WRITE_TO_DR, 40 | 41 | KILL_AUTOLOAD_MSR_READ, 42 | KILL_AUTOLOAD_MSR_WRITE, 43 | KILL_MSR_WRITE_SYSENTER_CS, 44 | KILL_MSR_WRITE_SYSENTER_ESP, 45 | KILL_MSR_WRITE_SYSENTER_EIP, 46 | KILL_MSR_WRITE_UNKNOWN, 47 | 48 | KILL_SGDT_SIDT, 49 | KILL_LGDT_LIDT, 50 | 51 | KILL_SLDT, 52 | KILL_STR, 53 | KILL_LLDT, 54 | KILL_LTR, 55 | 56 | KILL_IO_INSTRUCTION, 57 | 58 | KILL_FORBIDDEN_EXECVE, 59 | KILL_UNKNOWN_VMCALL, 60 | 61 | KILL_TRIPLE_FAULT, 62 | KILL_VM_ENTRY_INVALID_STATE, 63 | KILL_VM_ENTRY_FAILURE_MSR, 64 | KILL_UNKNOWN_EXIT_REASON, 65 | 66 | /* vmx instructions */ 67 | KILL_VMLAUNCH_FAILED, 68 | KILL_VMRESUME_FAILED, 69 | KILL_SWITCH_VM_TO_CAPSULE, 70 | 71 | /* memory */ 72 | KILL_TRACK_ALLOC_MEM_MAX, 73 | KILL_TRACK_ALLOC_FAILED, 74 | KILL_ALLOC_GUEST_PAGE, 75 | KILL_ALLOC_GUEST_PAGE_INSTALL_EPT, 76 | KILL_MAP_ARGV_ENVP_INSTALL_EPT, 77 | KILL_MAP_POLICIES_NOT_SET, 78 | KILL_MAP_POLICIES_INSTALL_EPT, 79 | 80 | /* devices host */ 81 | KILL_SHARE_DEVICE_MEM_INVALID_GPA, 82 | KILL_SHARE_DEVICE_MEM_TOO_MUCH_CALL, 83 | 84 | /* interrupts */ 85 | KILL_XCHAN_VECTOR_BUG, 86 | KILL_DOUBLE_FAULT, 87 | KILL_HARD_EXCEPTION_BUG, 88 | KILL_EXCEPTION_OR_NMI_BUG, 89 | 90 | /* ept */ 91 | KILL_PUD_ALLOC_FAILED, 92 | KILL_PMD_ALLOC_FAILED, 93 | KILL_PTE_ALLOC_FAILED, 94 | 95 | KILL_REMOVE_GPA_BAD_PUD, 96 | KILL_REMOVE_GPA_HUGE_PUD, 97 | KILL_REMOVE_GPA_BAD_PMD, 98 | KILL_REMOVE_GPA_LARGE_PMD, 99 | KILL_REMOVE_GPA_BAD_PTE, 100 | 101 | KILL_DUP_PAGE_FAILED, 102 | KILL_SELF_MODIF_CODE_INSTALL_EPT, 103 | 104 | KILL_EPT_VIOLATION_LOOP, 105 | KILL_EPT_VIOLATION_INSTALL_EPT, 106 | KILL_EPT_MISCONFIGURATION, 107 | 108 | /* log */ 109 | KILL_DMESG_INVALID_ADDR, 110 | 111 | /* xchan */ 112 | KILL_XCHAN_MAP_INVALID_INDEX, 113 | KILL_XCHAN_MAP_PAGES, 114 | KILL_XCHAN_CLOSED_NET, 115 | KILL_XCHAN_CLOSED_GUI, 116 | KILL_XCHAN_CLOSED_FS, 117 | KILL_XCHAN_CLOSED_CONSOLE, 118 | KILL_XCHAN_CLOSED_INVALID, 119 | 120 | /* capsule error */ 121 | KILL_CAPSULE_ERROR, 122 | 123 | MAX_KILL_REASON, 124 | } kill_t; 125 | 126 | 127 | #ifndef RELEASE 128 | 129 | #define KILL_MSG_FMT "%s" 130 | 131 | extern const char *kill_messages[]; 132 | 133 | static inline const char *kill_msg(kill_t reason) 134 | { 135 | unsigned int msg_index = reason; 136 | 137 | if (msg_index >= MAX_KILL_REASON) 138 | return "invalid kill reason"; 139 | else 140 | return kill_messages[msg_index]; 141 | } 142 | 143 | #else 144 | 145 | #define KILL_MSG_FMT "%d" 146 | 147 | static inline int kill_msg(kill_t reason) 148 | { 149 | return reason; 150 | } 151 | 152 | #endif /* RELEASE */ 153 | 154 | #endif /* CUAPI_KILL_H */ 155 | -------------------------------------------------------------------------------- /include/cuapi/common/kill_msg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_KILL_MSG_H 18 | #define CUAPI_KILL_MSG_H 19 | 20 | #include "cuapi/common/kill.h" 21 | 22 | #ifndef RELEASE 23 | 24 | #ifndef BUILD_BUG_ON 25 | #define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) 26 | #endif 27 | 28 | #define X(k, v) [k] = v, 29 | 30 | #define ENUM_MAP(X) \ 31 | X(KILL_VMCALL_EXIT, "encapsulated process exited") \ 32 | X(KILL_VMCALL_FATAL_SIGNAL, "shadow process received fatal signal") \ 33 | \ 34 | /* VM-exits */ \ 35 | X(KILL_MOVE_TO_CR0, "write invalid CR0 value") \ 36 | X(KILL_MOVE_TO_CR4, "write invalid CR4 value") \ 37 | X(KILL_MOVE_TO_CR8, "write to CR8") \ 38 | X(KILL_MOVE_TO_CRX, "write to unknown control register (BUG)") \ 39 | \ 40 | X(KILL_CLTS, "execution of CLTS") \ 41 | \ 42 | X(KILL_MOVE_FROM_CR0_BUG, "CR0 read (BUG)") \ 43 | X(KILL_MOVE_FROM_CR4_BUG, "CR4 read (BUG)") \ 44 | X(KILL_MOVE_FROM_CR8, "CR8 read") \ 45 | X(KILL_MOVE_FROM_CRX, "read unknown control register (BUG)") \ 46 | \ 47 | X(KILL_LMSW_TODO, "execution of LMSW (TODO)") \ 48 | \ 49 | X(KILL_WRITE_TO_DR, "write to debug register") \ 50 | \ 51 | X(KILL_AUTOLOAD_MSR_READ, "read from unknown autoload MSR (BUG)") \ 52 | X(KILL_AUTOLOAD_MSR_WRITE, "write to unknown autoload MSR (BUG)") \ 53 | X(KILL_MSR_WRITE_SYSENTER_CS, "write to SYSENTER_CS MSR") \ 54 | X(KILL_MSR_WRITE_SYSENTER_ESP, "write to SYSENTER_ESP MSR") \ 55 | X(KILL_MSR_WRITE_SYSENTER_EIP, "write to SYSENTER_EIP MSR") \ 56 | X(KILL_MSR_WRITE_UNKNOWN, "write to unknown MSR") \ 57 | \ 58 | X(KILL_SGDT_SIDT, "execution of SGDT/SIDT") \ 59 | X(KILL_LGDT_LIDT, "execution of LGDT/LIDT") \ 60 | \ 61 | X(KILL_SLDT, "execution of SLDT") \ 62 | X(KILL_STR, "execution of STR") \ 63 | X(KILL_LLDT, "execution of LLDT") \ 64 | X(KILL_LTR, "execution of LTR") \ 65 | \ 66 | X(KILL_IO_INSTRUCTION, "execution of an I/O instruction") \ 67 | \ 68 | X(KILL_FORBIDDEN_EXECVE, "forbidden execve") \ 69 | X(KILL_UNKNOWN_VMCALL, "unknown VMCALL") \ 70 | \ 71 | X(KILL_TRIPLE_FAULT, "triple fault") \ 72 | X(KILL_VM_ENTRY_INVALID_STATE, "VM-entry invalid state") \ 73 | X(KILL_VM_ENTRY_FAILURE_MSR, "VM-entry failure") \ 74 | X(KILL_UNKNOWN_EXIT_REASON, "unknown exit reason (BUG)") \ 75 | \ 76 | /* vmx instructions */ \ 77 | X(KILL_VMLAUNCH_FAILED, "VMLAUNCH failed") \ 78 | X(KILL_VMRESUME_FAILED, "VMRESUME failed") \ 79 | X(KILL_SWITCH_VM_TO_CAPSULE, "VMLOAD failed (BUG)") \ 80 | \ 81 | /* memory */ \ 82 | X(KILL_TRACK_ALLOC_MEM_MAX, "capsule's memory limit reached") \ 83 | X(KILL_TRACK_ALLOC_FAILED, "memory allocation failed (track alloc)") \ 84 | X(KILL_ALLOC_GUEST_PAGE, "memory allocation failed (guest page)") \ 85 | X(KILL_ALLOC_GUEST_PAGE_INSTALL_EPT, "install EPT translation failed (alloc guest page)") \ 86 | X(KILL_MAP_ARGV_ENVP_INSTALL_EPT, "install EPT translation failed (map argv)") \ 87 | X(KILL_MAP_POLICIES_NOT_SET, "exec policies not set (BUG)") \ 88 | X(KILL_MAP_POLICIES_INSTALL_EPT, "install EPT translation failed (exec policies)") \ 89 | \ 90 | /* devices host */ \ 91 | X(KILL_SHARE_DEVICE_MEM_INVALID_GPA, "invalid GPA for shared mem") \ 92 | X(KILL_SHARE_DEVICE_MEM_TOO_MUCH_CALL, "too much SHARE_MEM VMCALLs") \ 93 | \ 94 | /* interrupts */ \ 95 | X(KILL_XCHAN_VECTOR_BUG, "invalid I/O vector (BUG)") \ 96 | X(KILL_DOUBLE_FAULT, "double fault") \ 97 | X(KILL_HARD_EXCEPTION_BUG, "invalid hard exception (BUG)") \ 98 | X(KILL_EXCEPTION_OR_NMI_BUG, "invalid exception or NMI (BUG)") \ 99 | \ 100 | /* ept */ \ 101 | X(KILL_PUD_ALLOC_FAILED, "memory allocation failed (PUD)") \ 102 | X(KILL_PMD_ALLOC_FAILED, "memory allocation failed (PMD)") \ 103 | X(KILL_PTE_ALLOC_FAILED, "memory allocation failed (PTE)") \ 104 | \ 105 | X(KILL_REMOVE_GPA_BAD_PUD, "remove EPT translation failed (bad PUD)") \ 106 | X(KILL_REMOVE_GPA_HUGE_PUD, "remove EPT translation failed (huge PUD)") \ 107 | X(KILL_REMOVE_GPA_BAD_PMD, "remove EPT translation failed (bad PMD)") \ 108 | X(KILL_REMOVE_GPA_LARGE_PMD, "remove EPT translation failed (large PMD)") \ 109 | X(KILL_REMOVE_GPA_BAD_PTE, "remove EPT translation failed (bad PTE)") \ 110 | \ 111 | X(KILL_DUP_PAGE_FAILED, "memory allocation failed (dup page)") \ 112 | X(KILL_SELF_MODIF_CODE_INSTALL_EPT, "install EPT translation failed (self-modifying code)") \ 113 | \ 114 | X(KILL_EPT_VIOLATION_LOOP, "loop in EPT violation (BUG)") \ 115 | X(KILL_EPT_VIOLATION_INSTALL_EPT, "install EPT translation failed (EPT violation)") \ 116 | X(KILL_EPT_MISCONFIGURATION, "EPT misconfiguration (BUG)") \ 117 | \ 118 | /* log */ \ 119 | X(KILL_DMESG_INVALID_ADDR, "invalid address in dmesg") \ 120 | \ 121 | /* xchan */ \ 122 | X(KILL_XCHAN_MAP_INVALID_INDEX, "xchan: invalid index") \ 123 | X(KILL_XCHAN_MAP_PAGES, "xchan: can't map pages") \ 124 | X(KILL_XCHAN_CLOSED_NET, "xchan: net closed") \ 125 | X(KILL_XCHAN_CLOSED_GUI, "xchan: gui closed") \ 126 | X(KILL_XCHAN_CLOSED_FS, "xchan: fs closed") \ 127 | X(KILL_XCHAN_CLOSED_CONSOLE, "xchan: console closed") \ 128 | X(KILL_XCHAN_CLOSED_INVALID, "xchan: invalid closed") \ 129 | \ 130 | /* capsule error */ \ 131 | X(KILL_CAPSULE_ERROR, "capsule error") 132 | 133 | const char *kill_messages[] = { 134 | ENUM_MAP(X) 135 | }; 136 | #undef X 137 | 138 | #define X(n, v) + 1 139 | #define NB_MSG (0 ENUM_MAP(X)) 140 | 141 | /* ensure at compile time that each kill_t has an index in kill_messages 142 | * array */ 143 | void check_array_size_at_compile_time(void) 144 | { 145 | BUILD_BUG_ON(NB_MSG != MAX_KILL_REASON); 146 | } 147 | 148 | #endif /* RELEASE */ 149 | 150 | #endif /* CUAPI_KILL_MSG_H */ 151 | -------------------------------------------------------------------------------- /include/cuapi/common/process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_COMMON_PROCESS_H 18 | #define CUAPI_COMMON_PROCESS_H 19 | 20 | #include 21 | 22 | enum pid_index { 23 | PID_INDEX_FS = 0, 24 | PID_INDEX_GUI, 25 | PID_INDEX_NET, 26 | PID_INDEX_XORG, 27 | PID_INDEX_MAX, 28 | }; 29 | 30 | struct allowed_pids { 31 | pid_t pids[PID_INDEX_MAX]; 32 | }; 33 | 34 | #endif /* CUAPI_COMMON_PROCESS_H */ 35 | -------------------------------------------------------------------------------- /include/cuapi/common/stats.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_COMMON_STATS_H 18 | #define CUAPI_COMMON_STATS_H 19 | 20 | #include "cuapi/common/vmcall.h" 21 | 22 | struct event_counter { 23 | __u64 count; 24 | struct timespec elapsed_time; 25 | }; 26 | 27 | #define NR_VM_EXIT_REASONS 64 28 | 29 | /* 30 | * Structure storing capsule statistics. 31 | */ 32 | struct capsule_stats { 33 | /* Counters for VM-exits. */ 34 | struct event_counter vm_exits[NR_VM_EXIT_REASONS]; 35 | 36 | /* Counters for VM-calls. */ 37 | struct event_counter vm_calls[NR_CAPSULE_VM_CALLS]; 38 | 39 | /* Number of injected timer interrupts. */ 40 | __u64 nr_local_timer_intr; 41 | 42 | /* Number of injected xchan interrupts. */ 43 | __u64 nr_xchan_intr; 44 | 45 | /* Number of context switches. */ 46 | __u64 nr_switches; 47 | 48 | /* Time spent in capsule mode. */ 49 | struct timespec total_elapsed_time; 50 | }; 51 | 52 | struct vmm_stats { 53 | struct event_counter vm_exits[NR_VM_EXIT_REASONS]; 54 | struct event_counter xchan_guest_notif; 55 | }; 56 | 57 | struct cappsule_ioc_stats { 58 | unsigned int capsule_id; 59 | struct capsule_stats stats; 60 | }; 61 | 62 | struct cappsule_ioc_vmm_stats { 63 | unsigned int cpu; 64 | struct vmm_stats stats; 65 | }; 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /include/cuapi/common/uuid.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_UUID_H 18 | #define CUAPI_UUID_H 19 | 20 | #ifdef __KERNEL__ 21 | #include 22 | #else 23 | #include 24 | #endif 25 | 26 | struct uuid { 27 | uint32_t timelow; 28 | uint16_t timemid; 29 | uint16_t version_timehigh; 30 | uint8_t variant_clockseqhigh; 31 | uint8_t clockseqlow; 32 | uint8_t node[6]; 33 | }; 34 | 35 | #endif /* CUAPI_UUID_H */ 36 | -------------------------------------------------------------------------------- /include/cuapi/common/vmcall.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_COMMON_VMCALL_H 18 | #define CUAPI_COMMON_VMCALL_H 19 | 20 | enum vmcall_reason { 21 | /* vmcalls for trusted guest */ 22 | VMCALL_STOP_VMM = 0, 23 | VMCALL_SNAPSHOT, 24 | VMCALL_CREATE_CAPSULE, 25 | VMCALL_LAUNCH_CAPSULE, 26 | VMCALL_RESUME_EXECUTION, 27 | VMCALL_FATAL_SIGNAL, 28 | VMCALL_XCHAN_SET_EVENT, 29 | VMCALL_ADD_PENDING_TIMER_INTR, 30 | VMCALL_ADD_PENDING_XCHAN_INTR, 31 | VMCALL_GPA_TO_HVA, 32 | VMCALL_KILLALL, 33 | VMCALL_GET_SHADOWP_TASK, 34 | VMCALL_GET_FIRST_SHADOWP_TASK, 35 | VMCALL_GET_CAPSULE_STATS, 36 | VMCALL_GET_CAPSULE_IDS, 37 | VMCALL_RESIZE_CONSOLE, 38 | 39 | /* vmcalls for capsule */ 40 | VMCALL_CAPSULE_START, 41 | VMCALL_EXIT = VMCALL_CAPSULE_START, 42 | VMCALL_FORBIDDEN_EXECVE, 43 | VMCALL_SHARE_MEM, 44 | VMCALL_GETTIMEOFDAY, 45 | VMCALL_SET_TIMER, 46 | VMCALL_XCHAN_NOTIFY_TRUSTED, 47 | VMCALL_XCHAN_MAP_GUEST_PAGE, 48 | VMCALL_XCHAN_CLOSED, 49 | VMCALL_CAPSULE_ERROR, 50 | 51 | /* number of VM calls, not a real call type */ 52 | NR_VM_CALLS 53 | }; 54 | #define NR_CAPSULE_VM_CALLS (NR_VM_CALLS - VMCALL_CAPSULE_START - 1) 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /include/cuapi/common/xchan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_COMMON_XCHAN_H 18 | #define CUAPI_COMMON_XCHAN_H 19 | 20 | enum xchan_type { 21 | XCHAN_NET = 0, 22 | XCHAN_GUI, 23 | XCHAN_FS, 24 | XCHAN_CONSOLE, 25 | XCHAN_TYPE_MAX 26 | }; 27 | 28 | #define XCHAN_NPAGES_NET (64 * 2) 29 | #define XCHAN_NPAGES_GUI (8 * 2) 30 | #define XCHAN_NPAGES_FS (33 * 2) 31 | #define XCHAN_NPAGES_CONSOLE (8 * 2) 32 | 33 | #define XCHAN_NPAGES_TOTAL ( \ 34 | XCHAN_NPAGES_NET + \ 35 | XCHAN_NPAGES_GUI + \ 36 | XCHAN_NPAGES_FS + \ 37 | XCHAN_NPAGES_CONSOLE \ 38 | ) 39 | 40 | static inline unsigned int xchan_npages(enum xchan_type type) 41 | { 42 | unsigned int npages; 43 | 44 | switch (type) { 45 | case XCHAN_CONSOLE: npages = XCHAN_NPAGES_CONSOLE; break; 46 | case XCHAN_FS: npages = XCHAN_NPAGES_FS; break; 47 | case XCHAN_GUI: npages = XCHAN_NPAGES_GUI; break; 48 | case XCHAN_NET: npages = XCHAN_NPAGES_NET; break; 49 | default: npages = 0; break; 50 | } 51 | 52 | return npages; 53 | } 54 | 55 | static inline int xchan_start_page(enum xchan_type type) 56 | { 57 | unsigned int start; 58 | 59 | start = -1; 60 | 61 | /* note there's no break (instead for default) */ 62 | switch (type) { 63 | case XCHAN_NET: start += XCHAN_NPAGES_GUI; 64 | case XCHAN_GUI: start += XCHAN_NPAGES_FS; 65 | case XCHAN_FS: start += XCHAN_NPAGES_CONSOLE; 66 | case XCHAN_CONSOLE: start += 1; 67 | default: break; 68 | } 69 | 70 | return start; 71 | } 72 | 73 | #endif /* CUAPI_COMMON_XCHAN_H */ 74 | -------------------------------------------------------------------------------- /include/cuapi/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_ERROR_H 18 | #define CUAPI_ERROR_H 19 | 20 | #define CAPPSULE_ERRNO_BASE 256 21 | 22 | enum hv_error { 23 | HV_SUCCESS = 0, 24 | 25 | /* hypervisor initialisation */ 26 | ERROR_ALLOC_GUARD_PAGE, 27 | ERROR_ALLOC_FAILED, 28 | ERROR_LOG_DEVICE_REGISTRATION, 29 | ERROR_SYMBOL_RESOLUTION, 30 | ERROR_CHECK_BREAKPOINTS, 31 | ERROR_XCHAN_INTR_VECTOR, 32 | ERROR_MFN_DEVICE_REGISTRATION, 33 | ERROR_SHRINK_MEMORY, 34 | ERROR_VMX_ALREADY_ENABLED, 35 | ERROR_VMLAUNCH_FAILED, 36 | ERROR_VMXON_FAILED, 37 | ERROR_CPU_FORK, 38 | ERROR_CPU_NO_VMX, 39 | ERROR_CPU_NO_SECONDARY_CONTROLS, 40 | ERROR_CPU_NO_EPT, 41 | ERROR_CPU_VMX_DISABLED, 42 | ERROR_CPU_WB_MEMORY_TYPE, 43 | ERROR_CPU_NO_INVEPT, 44 | ERROR_CPU_INVEPT_ALL_CONTEXT, 45 | ERROR_CLEAR_TRUSTED_VMCS, 46 | ERROR_LOAD_TRUSTED_VMCS, 47 | ERROR_CLEAR_CAPSULE_VMCS, 48 | ERROR_LOAD_CAPSULE_VMCS, 49 | 50 | /* snapshot */ 51 | ERROR_SNAP_ALREADY_DONE, 52 | ERROR_SNAP_MODULE_BEING_REMOVED, 53 | ERROR_SNAP_PARAMS_NPAGES_TOO_LARGE, 54 | ERROR_SNAP_CPUS_ONLINE, 55 | ERROR_SNAP_FIX_SET_HOOK, 56 | ERROR_SNAP_FIX_INVALID_ADDR, 57 | ERROR_SNAP_FIX_MULTIPLE_PAGES, 58 | ERROR_SNAP_ERASE_MODULE_MEMORY, 59 | ERROR_SNAP_ARGV_GPA, 60 | 61 | ERROR_SNAP_PID_BITMAP_ALLOC_FAILED, 62 | ERROR_SNAP_SET_PFN_ALLOC_FAILED, 63 | ERROR_SNAP_ALLOC_COPY_PAGES, 64 | ERROR_SNAP_COUNT_DATA_PAGES, 65 | ERROR_SNAP_CREATE_SNAP_ALLOC_FAILED, 66 | ERROR_SNAP_INVALID_PTE, 67 | ERROR_SNAP_PTE_LEVEL_SET, 68 | 69 | /* capsule creation */ 70 | ERROR_CREATION_NO_SNAPSHOT, 71 | ERROR_CREATION_MODULE_BEING_REMOVED, 72 | ERROR_CREATION_MAX_CAPSULE, 73 | ERROR_CREATION_ALLOC_FAILED, 74 | ERROR_CREATION_INVALID_USER_PAGES, 75 | ERROR_CREATION_XCHAN_ALLOC_FAILED, 76 | ERROR_CREATION_KTHREAD_FAILED, 77 | 78 | /* xchan */ 79 | ERROR_XCHAN_DEVICE_REGISTRATION, 80 | 81 | HV_ERROR_MAX 82 | }; 83 | 84 | #endif /* CUAPI_ERROR_H */ 85 | -------------------------------------------------------------------------------- /include/cuapi/guest/console.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_GUEST_CONSOLE_H 18 | #define CUAPI_GUEST_CONSOLE_H 19 | 20 | #define GUEST_CONSOLE_DEVICE_BASENAME "cappsule-tty" 21 | #define GUEST_CONSOLE_DEVICE_NAME GUEST_CONSOLE_DEVICE_BASENAME "0" 22 | 23 | #endif /* CUAPI_GUEST_CONSOLE_H */ 24 | -------------------------------------------------------------------------------- /include/cuapi/guest/mfn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_GUEST_MFN_H 18 | #define CUAPI_GUEST_MFN_H 19 | 20 | #define MFN_IOC_MAGIC 'C' 21 | #define MFN_GET _IOR(MFN_IOC_MAGIC, 1, int) 22 | 23 | #define GUEST_MFN_DEVICE_NAME "mfn" 24 | 25 | #endif /* CUAPI_GUEST_MFN_H */ 26 | -------------------------------------------------------------------------------- /include/cuapi/guest/xchan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_GUEST_XCHAN_H 18 | #define CUAPI_GUEST_XCHAN_H 19 | 20 | #include "cuapi/common/xchan.h" 21 | 22 | #define GUEST_XCHAN_DEVICE_NAME "xchan" 23 | 24 | #define XCHAN_IOC_GUEST_MAGIC 'G' 25 | #define XCHAN_IOC_GUEST_SET_INFOS _IOW(XCHAN_IOC_GUEST_MAGIC, 0, int) 26 | #define XCHAN_IOC_GUEST_NOTIFY _IOW(XCHAN_IOC_GUEST_MAGIC, 1, struct xchan_guest_ioctl) 27 | 28 | struct xchan_guest_ioctl { 29 | enum xchan_type type; 30 | int eventfd; 31 | }; 32 | 33 | #endif /* CUAPI_GUEST_XCHAN_H */ 34 | -------------------------------------------------------------------------------- /include/cuapi/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_LOG_H 18 | #define CUAPI_LOG_H 19 | 20 | #define LOG_DEVICE "cappsule-log" 21 | #define LOG_LINE_MAX 1024 22 | 23 | enum CPSL_LOG_FACILIY { 24 | LOG_HV, /* message about hypervisor */ 25 | LOG_CPSL, /* message about cappsule */ 26 | LOG_TG, /* message about trusted guest */ 27 | }; 28 | 29 | enum CPSL_LOG_LEVEL { 30 | CPSL_ERR, 31 | CPSL_WARN, 32 | CPSL_INFO, 33 | CPSL_DEBUG, 34 | CPSL_DMESG, /* printk from capsule */ 35 | }; 36 | 37 | struct log_header { 38 | unsigned long timestamp; 39 | unsigned short size; 40 | unsigned short id; 41 | unsigned char level; 42 | unsigned char facility; 43 | } __attribute__((packed)); 44 | 45 | struct log_entry { 46 | struct log_header header; 47 | char buffer[LOG_LINE_MAX]; 48 | }; 49 | 50 | #endif /* CUAPI_LOG_H */ 51 | -------------------------------------------------------------------------------- /include/cuapi/trusted/channel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_TRUSTED_CHANNEL_H 18 | #define CUAPI_TRUSTED_CHANNEL_H 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #ifdef __KERNEL__ 25 | #include 26 | #else 27 | #include 28 | #endif 29 | 30 | #include "cuapi/common/kill.h" 31 | #include "cuapi/common/uuid.h" 32 | 33 | /* Maximum number of capsules running simultaneously.*/ 34 | #define MAX_CAPSULE 32 35 | 36 | #define CHANNEL_DEVICE_NAME "cappsule" 37 | 38 | #define CAPPSULE_IOC_MAGIC 'C' 39 | #define CAPPSULE_IOC_SET_PIDS _IOW(CAPPSULE_IOC_MAGIC, 0, struct allowed_pids) 40 | #define CAPPSULE_IOC_SNAPSHOT _IOW(CAPPSULE_IOC_MAGIC, 1, struct cappsule_ioc_snapshot *) 41 | #define CAPPSULE_IOC_SET_EXEC_POLICIES _IOW(CAPPSULE_IOC_MAGIC, 2, int) 42 | #define CAPPSULE_IOC_CREATE_CAPSULE _IOWR(CAPPSULE_IOC_MAGIC, 3, struct cappsule_ioc_create *) 43 | #define CAPPSULE_IOC_KILL_CAPSULE _IOWR(CAPPSULE_IOC_MAGIC, 4, unsigned int) 44 | #define CAPPSULE_IOC_GET_CAPSULE_STATS _IOWR(CAPPSULE_IOC_MAGIC, 5, struct cappsule_ioc_stats *) 45 | #define CAPPSULE_IOC_GET_VMM_STATS _IOWR(CAPPSULE_IOC_MAGIC, 6, struct capsule_ioc_vmm_stats *) 46 | #define CAPPSULE_IOC_LIST_CAPSULES _IOWR(CAPPSULE_IOC_MAGIC, 7, struct cappsule_ioc_list *) 47 | 48 | struct cappsule_ioc_policies { 49 | #ifdef __KERNEL__ 50 | void __user *buf; 51 | #else 52 | void *buf; 53 | #endif 54 | size_t size; 55 | }; 56 | 57 | struct cappsule_ioc_snapshot { 58 | void *params; 59 | unsigned int params_size; 60 | unsigned int result_capsule_id; /* set by kernel of capsule */ 61 | }; 62 | 63 | struct cappsule_ioc_create { 64 | void *params; 65 | struct uuid policy_uuid; 66 | bool no_gui; 67 | struct winsize tty_size; 68 | unsigned int memory_limit; /* in MB */ 69 | uid_t uid; 70 | 71 | unsigned int result_capsule_id; /* set by kernel */ 72 | }; 73 | 74 | struct cappsule_ioc_list { 75 | size_t nr_capsules; 76 | unsigned int capsule_ids[0]; 77 | }; 78 | 79 | struct capsule_event_kill { 80 | unsigned int capsule_id; 81 | kill_t reason; 82 | }; 83 | 84 | #endif /* CUAPI_TRUSTED_CHANNEL_H */ 85 | -------------------------------------------------------------------------------- /include/cuapi/trusted/mfn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_HOST_MFN_H 18 | #define CUAPI_HOST_MFN_H 19 | 20 | struct host_mfn { 21 | unsigned int capsule_id; 22 | #ifdef __KERNEL__ 23 | unsigned long __user *user_pfntable; 24 | #else 25 | unsigned long *pfntable; 26 | #endif /* __KERNEL__ */ 27 | unsigned long num_mfn; 28 | }; 29 | 30 | #endif /* CUAPI_HOST_MFN_H */ 31 | -------------------------------------------------------------------------------- /include/cuapi/trusted/xchan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef CUAPI_TRUSTED_XCHAN_H 18 | #define CUAPI_TRUSTED_XCHAN_H 19 | 20 | #include "cuapi/common/xchan.h" 21 | 22 | #define TRUSTED_XCHAN_DEVICE_NAME "cappsule-xchan" 23 | 24 | #define CAPPSULE_IOC_XCHAN_MAGIC 'T' 25 | #define CAPPSULE_IOC_XCHAN_INFOS _IOW(CAPPSULE_IOC_XCHAN_MAGIC, 0, struct xchan_ioctl *) 26 | #define CAPPSULE_IOC_XCHAN_NOTIFY _IOW(CAPPSULE_IOC_XCHAN_MAGIC, 1, unsigned int) 27 | #define CAPPSULE_IOC_XCHAN_CONSOLE_RESIZE _IOW(CAPPSULE_IOC_XCHAN_MAGIC, 2, struct winsize *) 28 | 29 | struct winsize; 30 | 31 | struct xchan_ioctl { 32 | unsigned int capsule_id; 33 | enum xchan_type type; 34 | int eventfd; 35 | }; 36 | 37 | #endif /* CUAPI_TRUSTED_XCHAN_H */ 38 | -------------------------------------------------------------------------------- /include/guest/console.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef GUEST_CONSOLE_H 18 | #define GUEST_CONSOLE_H 19 | 20 | #include "cuapi/guest/console.h" 21 | 22 | void wake_up_console_processes(void); 23 | void guest_tty_init(void); 24 | 25 | #endif /* GUEST_CONSOLE_H */ 26 | -------------------------------------------------------------------------------- /include/guest/init.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _DEVICES_GUEST_INIT_H 18 | #define _DEVICES_GUEST_INIT_H 19 | 20 | #include "common/vmcall.h" 21 | 22 | #define guest_error(fmt, ...) do { \ 23 | printk(KERN_ERR fmt "\n", ##__VA_ARGS__); \ 24 | cpu_vmcs_vmcall(VMCALL_CAPSULE_ERROR, 0); \ 25 | } while (0) 26 | 27 | void guest_init(void); 28 | 29 | #endif /* _DEVICES_GUEST_INIT_H */ 30 | -------------------------------------------------------------------------------- /include/guest/kernel_sched_sched.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | /* 18 | * kernel/sched/sched.h is not exported 19 | * 20 | * List of changes: 21 | * - 9d89c257dfb9c51a532d69397f6eed75e5168c35 22 | * - 139622343ef31941effc6de6a5a9320371a00e62 23 | */ 24 | 25 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,2,6) 26 | struct cfs_rq { 27 | struct load_weight load; 28 | unsigned int nr_running, h_nr_running; 29 | 30 | u64 exec_clock; 31 | u64 min_vruntime; 32 | #ifndef CONFIG_64BIT 33 | u64 min_vruntime_copy; 34 | #endif 35 | 36 | struct rb_root tasks_timeline; 37 | struct rb_node *rb_leftmost; 38 | 39 | /* 40 | * 'curr' points to currently running entity on this cfs_rq. 41 | * It is set to NULL otherwise (i.e when none are currently running). 42 | */ 43 | struct sched_entity *curr, *next, *last, *skip; 44 | 45 | #ifdef CONFIG_SCHED_DEBUG 46 | unsigned int nr_spread_over; 47 | #endif 48 | 49 | #ifdef CONFIG_SMP 50 | /* 51 | * CFS Load tracking 52 | */ 53 | struct sched_avg avg; 54 | u64 runnable_load_sum; 55 | unsigned long runnable_load_avg; 56 | #ifdef CONFIG_FAIR_GROUP_SCHED 57 | unsigned long tg_load_avg_contrib; 58 | #endif 59 | atomic_long_t removed_load_avg, removed_util_avg; 60 | #ifndef CONFIG_64BIT 61 | u64 load_last_update_time_copy; 62 | #endif 63 | 64 | #ifdef CONFIG_FAIR_GROUP_SCHED 65 | /* 66 | * h_load = weight * f(tg) 67 | * 68 | * Where f(tg) is the recursive weight fraction assigned to 69 | * this group. 70 | */ 71 | unsigned long h_load; 72 | u64 last_h_load_update; 73 | struct sched_entity *h_load_next; 74 | #endif /* CONFIG_FAIR_GROUP_SCHED */ 75 | #endif /* CONFIG_SMP */ 76 | 77 | #ifdef CONFIG_FAIR_GROUP_SCHED 78 | struct rq *rq; /* cpu runqueue to which this cfs_rq is attached */ 79 | 80 | /* 81 | * leaf cfs_rqs are those that hold tasks (lowest schedulable entity in 82 | * a hierarchy). Non-leaf lrqs hold other higher schedulable entities 83 | * (like users, containers etc.) 84 | * 85 | * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This 86 | * list is used during load balance. 87 | */ 88 | int on_list; 89 | struct list_head leaf_cfs_rq_list; 90 | struct task_group *tg; /* group that "owns" this runqueue */ 91 | 92 | #ifdef CONFIG_CFS_BANDWIDTH 93 | int runtime_enabled; 94 | u64 runtime_expires; 95 | s64 runtime_remaining; 96 | 97 | u64 throttled_clock, throttled_clock_task; 98 | u64 throttled_clock_task_time; 99 | int throttled, throttle_count; 100 | struct list_head throttled_list; 101 | #endif /* CONFIG_CFS_BANDWIDTH */ 102 | #endif /* CONFIG_FAIR_GROUP_SCHED */ 103 | }; 104 | 105 | #else 106 | 107 | struct cfs_rq { 108 | struct load_weight load; 109 | unsigned int nr_running, h_nr_running; 110 | 111 | u64 exec_clock; 112 | u64 min_vruntime; 113 | #ifndef CONFIG_64BIT 114 | u64 min_vruntime_copy; 115 | #endif 116 | 117 | struct rb_root tasks_timeline; 118 | struct rb_node *rb_leftmost; 119 | 120 | /* 121 | * 'curr' points to currently running entity on this cfs_rq. 122 | * It is set to NULL otherwise (i.e when none are currently running). 123 | */ 124 | struct sched_entity *curr, *next, *last, *skip; 125 | 126 | #ifdef CONFIG_SCHED_DEBUG 127 | unsigned int nr_spread_over; 128 | #endif 129 | 130 | #ifdef CONFIG_SMP 131 | /* 132 | * CFS Load tracking 133 | * Under CFS, load is tracked on a per-entity basis and aggregated up. 134 | * This allows for the description of both thread and group usage (in 135 | * the FAIR_GROUP_SCHED case). 136 | */ 137 | unsigned long runnable_load_avg, blocked_load_avg; 138 | atomic64_t decay_counter; 139 | u64 last_decay; 140 | atomic_long_t removed_load; 141 | 142 | #ifdef CONFIG_FAIR_GROUP_SCHED 143 | /* Required to track per-cpu representation of a task_group */ 144 | u32 tg_runnable_contrib; 145 | unsigned long tg_load_contrib; 146 | 147 | /* 148 | * h_load = weight * f(tg) 149 | * 150 | * Where f(tg) is the recursive weight fraction assigned to 151 | * this group. 152 | */ 153 | unsigned long h_load; 154 | u64 last_h_load_update; 155 | struct sched_entity *h_load_next; 156 | #endif /* CONFIG_FAIR_GROUP_SCHED */ 157 | #endif /* CONFIG_SMP */ 158 | 159 | #ifdef CONFIG_FAIR_GROUP_SCHED 160 | struct rq *rq; /* cpu runqueue to which this cfs_rq is attached */ 161 | 162 | /* 163 | * leaf cfs_rqs are those that hold tasks (lowest schedulable entity in 164 | * a hierarchy). Non-leaf lrqs hold other higher schedulable entities 165 | * (like users, containers etc.) 166 | * 167 | * leaf_cfs_rq_list ties together list of leaf cfs_rq's in a cpu. This 168 | * list is used during load balance. 169 | */ 170 | int on_list; 171 | struct list_head leaf_cfs_rq_list; 172 | struct task_group *tg; /* group that "owns" this runqueue */ 173 | 174 | #ifdef CONFIG_CFS_BANDWIDTH 175 | int runtime_enabled; 176 | u64 runtime_expires; 177 | s64 runtime_remaining; 178 | 179 | u64 throttled_clock, throttled_clock_task; 180 | u64 throttled_clock_task_time; 181 | int throttled, throttle_count; 182 | struct list_head throttled_list; 183 | #endif /* CONFIG_CFS_BANDWIDTH */ 184 | #endif /* CONFIG_FAIR_GROUP_SCHED */ 185 | }; 186 | #endif 187 | -------------------------------------------------------------------------------- /include/guest/mfn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef GUEST_MFN_H 18 | #define GUEST_MFN_H 19 | 20 | #include "cuapi/guest/mfn.h" 21 | 22 | void guest_mfn_init(void); 23 | 24 | #endif /* GUEST_MFN_H */ 25 | -------------------------------------------------------------------------------- /include/guest/process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef GUEST_PROCESS_H 18 | #define GUEST_PROCESS_H 19 | 20 | #include 21 | 22 | 23 | #endif /* GUEST_PROCESS_H */ 24 | -------------------------------------------------------------------------------- /include/guest/shared_mem.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _GUEST_SHARED_MEM_H 18 | #define _GUEST_SHARED_MEM_H 19 | 20 | #include "common/shared_mem.h" 21 | 22 | extern struct shared_mem *shared_mem; 23 | 24 | static inline void guest_get_self_policy_uuid(struct uuid *uuid) 25 | { 26 | *uuid = shared_mem->policy_uuid; 27 | } 28 | 29 | /* Host may try to access to guest memory (eg: during installation of xchan 30 | * pages), but EPT translation may not have been installed yet, because pages 31 | * have been allocated in guest, but not read nor written. 32 | * 33 | * Force EPT violation with read access just after allocation. */ 34 | static inline void trigger_ept_violation(unsigned long page) 35 | { 36 | volatile unsigned char c; 37 | unsigned char *addr; 38 | 39 | addr = (char *)page; 40 | c = addr[0]; 41 | } 42 | 43 | unsigned int guest_get_capsule_id(void); 44 | void setup_shared_mem(void); 45 | 46 | #endif /* _GUEST_SHARED_MEM_H */ 47 | -------------------------------------------------------------------------------- /include/guest/symbols.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef GUEST_SYMBOLS_H 18 | #define GUEST_SYMBOLS_H 19 | 20 | #include "common/symbols.h" 21 | 22 | struct rq; 23 | 24 | extern u32 *_net_secret; 25 | 26 | extern void (*_deactivate_task)(struct rq *rq, struct task_struct *p, 27 | int flags); 28 | extern void (*_irq_set_chip_and_handler_name)(unsigned int, struct irq_chip *, 29 | irq_flow_handler_t, const char *); 30 | extern void (*___schedule)(void); 31 | extern struct tick_device *(*_tick_get_device)(int cpu); 32 | 33 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,0,0) 34 | /* commit: b337a9380f7effd60d082569dd7e0b97a7549730 35 | * timer: Allocate per-cpu tvec_base's statically */ 36 | extern struct tvec_base *_tvec_bases[NR_CPUS]; 37 | #else 38 | extern struct tvec_base **_tvec_bases[NR_CPUS]; 39 | #endif 40 | 41 | extern struct symbol guest_symbols[]; 42 | extern struct per_cpu_symbol guest_per_cpu_symbols[]; 43 | 44 | #endif /* GUEST_SYMBOLS_H */ 45 | -------------------------------------------------------------------------------- /include/guest/timers.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _GUEST_TIMERS_H 18 | #define _GUEST_TIMERS_H 19 | 20 | void setup_timers(void); 21 | void guest_fix_timekeeping(void); 22 | void init_apic(void); 23 | 24 | #endif /* _GUEST_TIMERS_H */ 25 | -------------------------------------------------------------------------------- /include/guest/xchan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef GUEST_XCHAN_H 18 | #define GUEST_XCHAN_H 19 | 20 | #include "cuapi/guest/xchan.h" 21 | 22 | void guest_xchan_init(__u8 xchan_first_vector); 23 | 24 | #endif /* GUEST_XCHAN_H */ 25 | -------------------------------------------------------------------------------- /include/host/breakpoint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef BREAKPOINT_H 18 | #define BREAKPOINT_H 19 | 20 | #define INSTR_MOV_RBP_RSP "\x48\x89\xe5" 21 | #define INSTR_PUSH_RBP "\x55" 22 | #define INSTR_LEAVE (unsigned char)'\xc9' 23 | #define INSTR_RET (unsigned char)'\xc3' 24 | #define INSTR_INT3 (unsigned char)'\xcc' 25 | 26 | struct breakpoint { 27 | unsigned long addr; 28 | unsigned char code; 29 | }; 30 | 31 | extern struct breakpoint bp_do_exit, 32 | bp_schedule_end, 33 | bp_schedule_tail_end, 34 | bp_prepare_binprm, 35 | bp_vt_console_print, 36 | bp_process_one_work; 37 | 38 | struct vcpu; 39 | 40 | int handle_int3_hook(struct vcpu *vcpu); 41 | 42 | void unset_breakpoints(void); 43 | void set_breakpoints(void); 44 | 45 | #endif /* BREAKPOINT_H */ 46 | -------------------------------------------------------------------------------- /include/host/capsule.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_CAPSULE_H 18 | #define HOST_CAPSULE_H 19 | 20 | #include 21 | #include 22 | 23 | #include "common/error.h" 24 | #include "cuapi/common/kill.h" 25 | #include "cuapi/common/stats.h" 26 | #include "host/context.h" 27 | #include "host/vcpu.h" 28 | #include "host/xchan.h" 29 | 30 | 31 | #ifndef RELEASE 32 | # define ASSERT(x) BUG_ON(!(x)) 33 | #else 34 | # define ASSERT(x) do { } while (0) 35 | #endif 36 | 37 | #define CPSL_ARGV_SETUP 0x001 /* set as soon as argv[] and envp[] are maped */ 38 | #define CPSL_EXITED 0x002 /* capsule has been killed, but isn't decapsulated yet */ 39 | 40 | /* It's sufficient to define 2 unique VPIDs: one for trusted guest (EPT not in 41 | * use) and another one for capsules (EPT in use): 42 | * 43 | * If EPT is not in use, the logical processor associates all mappings it 44 | * creates with the current VPID, and it will use such mappings to translate 45 | * linear addresses. For that reason, a VMM should not use the same VPID for 46 | * different non-EPT guests that use different page tables. 47 | * 48 | * If EPT is in use, the logical processor associates all mappings it creates 49 | * with the value of bits 51:12 of current EPTP. If a VMM uses different EPTP 50 | * values for different guests, it may use the same VPID for those guests. 51 | * Doing so cannot result in one guest using translations that pertain to the 52 | * other. */ 53 | #define TRUSTED_GUEST_VPID 1 54 | #define CAPSULE_VPID 2 55 | 56 | /* struct guest_mem fits in one page */ 57 | #define CAPSULE_MEM_NPAGES ((PAGE_SIZE - sizeof(void *) - sizeof(unsigned int)) / sizeof(struct page *)) 58 | 59 | struct guest_mem { 60 | struct guest_mem *next; /* next list element */ 61 | unsigned int n; /* number of entries in pages */ 62 | struct page *pages[CAPSULE_MEM_NPAGES]; 63 | }; 64 | 65 | struct guest_memory { 66 | unsigned int npages; 67 | 68 | /* guest pages are stored in a linked list */ 69 | struct guest_mem *first; 70 | struct guest_mem *curr; 71 | }; 72 | 73 | struct pending_interrupt { 74 | /* Bitmap of enum interrupt_bit, small enough to be stored in a long. 75 | * Functions manipulating this bitmap don't require the atomic 76 | * guarantees because they're always called on capsule' cpu. */ 77 | unsigned long bitmap; 78 | }; 79 | 80 | union ept_pgd; 81 | struct shadow_process; 82 | struct capsule_params; 83 | 84 | struct capsule { 85 | struct vcpu *vcpu; 86 | struct vmcs_region *vmcs; 87 | struct list_head list; 88 | unsigned int id; 89 | int flags; 90 | struct kref refcount; 91 | 92 | union ept_pgd *ept_pgd; 93 | unsigned long fault_address; /* used to check if there's a loop in */ 94 | unsigned int nfault; /* EPT violations */ 95 | 96 | struct capsule_params *params; 97 | 98 | ktime_t last_schedule; 99 | 100 | struct context ctx; 101 | int fpu_used; 102 | struct shadow_process *shadowp; 103 | 104 | /* maximum number of pages that can be allocated */ 105 | unsigned long memory_max_npages; 106 | 107 | /* - page tables and copies of host kernel memory, 108 | * - memory allocated in the capsule. */ 109 | struct guest_memory pt_mem; 110 | struct guest_memory alloc_mem; 111 | 112 | struct pending_interrupt intr; 113 | struct shared_mem *shared_mem; 114 | struct hrtimer clock_timer; 115 | 116 | struct xchan xchan; 117 | 118 | /* Statistics. */ 119 | struct capsule_stats stats; 120 | }; 121 | 122 | static inline struct capsule *current_capsule(struct vcpu *vcpu) 123 | { 124 | ASSERT(vcpu->guest == GUEST_CAPSULE); 125 | ASSERT(vcpu->capsule != NULL); 126 | return vcpu->capsule; 127 | } 128 | 129 | static inline int intr_pending(struct capsule *capsule) 130 | { 131 | return capsule->intr.bitmap & (-1L); 132 | } 133 | 134 | void kill(struct vcpu *vcpu, kill_t reason); 135 | void kill_s(struct capsule *capsule, kill_t reason); 136 | err_t create_capsule(struct vcpu *vcpu, struct capsule_params *params, 137 | struct shadow_process *shadowp); 138 | 139 | struct capsule *get_capsule_from_id(unsigned int id); 140 | struct capsule *capsule_from_id(unsigned int id); 141 | void put_capsule(struct capsule *capsule); 142 | int get_capsule_ids(unsigned int *ids, size_t size); 143 | 144 | struct task_struct *get_shadow_process_task(unsigned int capsule_id); 145 | struct task_struct *get_first_shadow_process_task(bool *woken_up); 146 | 147 | void launch_capsule(struct vcpu *vcpu, struct capsule *capsule); 148 | 149 | #endif /* HOST_CAPSULE_H */ 150 | -------------------------------------------------------------------------------- /include/host/context.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_CONTEXT_H 18 | #define HOST_CONTEXT_H 19 | 20 | #include 21 | 22 | 23 | /* for the time being: 24 | * - MSR_KERNEL_GS_BASE */ 25 | #define AUTOLOAD_MSR_NUMBER 1 26 | 27 | /* Register order must not be altered: move_from_cr(), move_to_cr(), 28 | * exit_dr_access() (and probably other functions) relies on it. */ 29 | struct regs { 30 | unsigned long rax; 31 | unsigned long rcx; 32 | unsigned long rdx; 33 | unsigned long rbx; 34 | unsigned long rsp; 35 | unsigned long rbp; 36 | unsigned long rsi; 37 | unsigned long rdi; 38 | unsigned long r8; 39 | unsigned long r9; 40 | unsigned long r10; 41 | unsigned long r11; 42 | unsigned long r12; 43 | unsigned long r13; 44 | unsigned long r14; 45 | unsigned long r15; 46 | } __attribute__((__packed__)); 47 | 48 | /* MSR are handled by VMX: physical address of (struct vmx_msr_entry *) must be 49 | * specified. Even if they aren't saved and restored manually, it makes sense to 50 | * put this structure in context. */ 51 | struct context { 52 | struct regs regs; 53 | /* XXX: MSR-store and MSR-load addresses must be 16-byte aligned. It 54 | * doesn't make sense to use __attribute__ ((aligned (16))) because 55 | * allocation alignment can't be predicted? */ 56 | struct vmx_msr_entry autoload_msr[AUTOLOAD_MSR_NUMBER]; 57 | }; 58 | 59 | static inline void save_context(struct context *ctx, struct regs *regs) 60 | { 61 | memcpy(&ctx->regs, regs, sizeof(*regs)); 62 | } 63 | 64 | static inline void restore_context(struct context *ctx, struct regs *regs) 65 | { 66 | memcpy(regs, &ctx->regs, sizeof(*regs)); 67 | } 68 | 69 | static inline void init_autoload_msr(struct vmx_msr_entry *msr) 70 | { 71 | int i; 72 | 73 | memset(msr, 0, sizeof(*msr) * AUTOLOAD_MSR_NUMBER); 74 | msr[0].index = MSR_KERNEL_GS_BASE; 75 | 76 | for (i = 0; i < AUTOLOAD_MSR_NUMBER; i++) 77 | rdmsrl(msr[i].index, msr[i].value); 78 | } 79 | 80 | #endif /* HOST_CONTEXT_H */ 81 | -------------------------------------------------------------------------------- /include/host/ept.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _EPT_H 18 | #define _EPT_H 1 19 | 20 | #include 21 | 22 | #define EPT_PROT_READ (1 << 0) 23 | #define EPT_PROT_WRITE (1 << 1) 24 | #define EPT_PROT_EXEC (1 << 2) 25 | #define EPT_PROT_RW (EPT_PROT_READ | EPT_PROT_WRITE) 26 | #define EPT_PROT_RX (EPT_PROT_READ | EPT_PROT_EXEC) 27 | #define EPT_PROT_RWX (EPT_PROT_READ | EPT_PROT_WRITE | EPT_PROT_EXEC) 28 | 29 | 30 | /* PGD (PML4E) 31 | * 32 | * (N–1):12 Physical address of 4-KByte aligned EPT page-directory-pointer 33 | * table referenced by this entry 34 | * 35 | * Since no processors supporting the Intel 64 architecture support more than 36 | * 48 physical-address bits, the size of field "addr" is 36 bits. Ditto for 37 | * other structures. */ 38 | struct ept_pgd_bits { 39 | unsigned read :1; 40 | unsigned write :1; 41 | unsigned exec :1; 42 | unsigned reserved1 :5; 43 | unsigned accessed :1; 44 | unsigned ignored1 :3; 45 | unsigned long addr :36; 46 | unsigned reserved2 :4; 47 | unsigned ignored2 :12; 48 | } __attribute__((packed)); 49 | 50 | union ept_pgd { 51 | struct ept_pgd_bits bits; 52 | __u64 value; 53 | }; 54 | 55 | /* PUD (PDPTE) */ 56 | struct ept_pud_bits { 57 | unsigned read :1; 58 | unsigned write :1; 59 | unsigned exec :1; 60 | unsigned reserved1 :5; 61 | unsigned accessed :1; 62 | unsigned ignored1 :3; 63 | unsigned long addr :36; 64 | unsigned reserved2 :4; 65 | unsigned ignored2 :12; 66 | } __attribute__((packed)); 67 | 68 | union ept_pud { 69 | struct ept_pud_bits bits; 70 | __u64 value; 71 | }; 72 | 73 | /* PMD (PDE) */ 74 | struct ept_pmd_bits { 75 | unsigned read :1; 76 | unsigned write :1; 77 | unsigned exec :1; 78 | unsigned reserved1 :4; 79 | unsigned zero :1; 80 | unsigned accessed :1; 81 | unsigned ignored1 :3; 82 | unsigned long addr :36; 83 | unsigned reserved2 :4; 84 | unsigned ignored2 :12; 85 | } __attribute__((packed)); 86 | 87 | union ept_pmd { 88 | struct ept_pmd_bits bits; 89 | __u64 value; 90 | }; 91 | 92 | /* PTE */ 93 | struct ept_pte_bits { 94 | unsigned read :1; 95 | unsigned write :1; 96 | unsigned exec :1; 97 | unsigned mem_type :3; 98 | unsigned ignore_pat :1; 99 | unsigned ignored1 :1; 100 | unsigned accessed :1; 101 | unsigned dirty :1; 102 | unsigned ignored2 :2; 103 | unsigned long addr :36; 104 | unsigned reserved1 :4; 105 | unsigned ignored3 :11; 106 | unsigned suppress_ve :1; 107 | } __attribute__((packed)); 108 | 109 | union ept_pte { 110 | struct ept_pte_bits bits; 111 | __u64 value; 112 | }; 113 | 114 | /* bits 47:39 */ 115 | #define ept_pgd_index(x) ((x >> 39) & 0x1ff) 116 | 117 | /* bits 38:30 */ 118 | #define ept_pud_index(x) ((x >> 30) & 0x1ff) 119 | 120 | /* bits 29:21 */ 121 | #define ept_pmd_index(x) ((x >> 21) & 0x1ff) 122 | 123 | /* bits 20:12 */ 124 | #define ept_pte_index(x) ((x >> 12) & 0x1ff) 125 | 126 | static inline int ept_pgd_present(union ept_pgd *pgd) 127 | { 128 | return (pgd->value & 3) != 0; 129 | } 130 | 131 | static inline int ept_pud_present(union ept_pud *pud) 132 | { 133 | return (pud->value & 3) != 0; 134 | } 135 | 136 | static inline int ept_pmd_present(union ept_pmd *pmd) 137 | { 138 | return (pmd->value & 3) != 0; 139 | } 140 | 141 | static inline int ept_pte_present(union ept_pte *pte) 142 | { 143 | return (pte->value & 3) != 0; 144 | } 145 | 146 | static inline unsigned long get_pte_prot(pte_t hpa) 147 | { 148 | unsigned long prot; 149 | int force_exec = 1; 150 | 151 | prot = 0; 152 | 153 | if (pte_write(hpa)) 154 | prot |= EPT_PROT_RW; 155 | 156 | /* XXX: always force EPT execute access to 1. */ 157 | if (pte_exec(hpa) || force_exec) 158 | prot |= EPT_PROT_RX; 159 | 160 | return prot; 161 | } 162 | 163 | struct vmcall_gpa_hva_convert; 164 | struct capsule; 165 | struct vcpu; 166 | 167 | void exit_ept_violation(struct vcpu *vcpu); 168 | void exit_ept_misconfig(struct vcpu *vcpu); 169 | void *gpa_to_hva(struct capsule *capsule, unsigned long gpa, unsigned long *prot); 170 | int install_ept_translation(struct capsule *capsule, unsigned long gpa, 171 | unsigned long hpa, unsigned long prot); 172 | void remove_ept_translation(struct capsule *capsule, unsigned long gpa); 173 | unsigned long vmcall_gpa_to_hva(struct vmcall_gpa_hva_convert *convert); 174 | 175 | #endif /* _EPT_H */ 176 | -------------------------------------------------------------------------------- /include/host/interrupt.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_INTERRUPT_H 18 | #define HOST_INTERRUPT_H 19 | 20 | struct capsule; 21 | struct vcpu; 22 | 23 | void add_pending_intr(struct capsule *capsule, __u8 vector, int running); 24 | void vmcall_add_pending_timer_intr(unsigned int id); 25 | int vmcall_add_pending_xchan_intr(unsigned int id, __u8 vector); 26 | void exit_pending_intr(struct vcpu *vcpu); 27 | void exit_external_intr(struct vcpu *vcpu); 28 | void exit_exception_or_nmi(struct vcpu *vcpu, unsigned long exit_qualification); 29 | void resolve_interrupt_handlers(void); 30 | void inject_gp_exception(int error_code); 31 | void inject_ud_exception(void); 32 | int host_add_pending_xchan_intr(struct vcpu *vcpu, unsigned int id, __u8 vector); 33 | 34 | #endif /* HOST_INTERRUPT_H */ 35 | -------------------------------------------------------------------------------- /include/host/memory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_MEMORY_H 18 | #define HOST_MEMORY_H 19 | 20 | #include 21 | 22 | enum guest_mem_type { 23 | MEM_EPT, /* page allocated by host for EPT */ 24 | MEM_GUEST, /* page for guest memory */ 25 | }; 26 | 27 | struct capsule; 28 | struct winsize; 29 | struct vcpu; 30 | 31 | #define PTE_IGNORED_SHIFT 52 32 | #define PTE_IS_INVALID(pte) (pte_val(pte) == -1) 33 | #define INVALID_PTE __pte(-1) 34 | 35 | /* Bits 62:52 are ignored. Use them to store page table level */ 36 | static inline enum pg_level get_pte_level(pte_t pte) 37 | { 38 | return (pte.pte >> PTE_IGNORED_SHIFT) & 0x7ff; 39 | } 40 | 41 | static inline int set_pte_level(pte_t *pte, enum pg_level level) 42 | { 43 | if (get_pte_level(*pte) != 0) 44 | return -1; 45 | 46 | pte->pte |= ((unsigned long)level << PTE_IGNORED_SHIFT); 47 | return 0; 48 | } 49 | 50 | pte_t get_host_pte(unsigned long pfn, enum pg_level *level); 51 | void free_capsule_mem(struct capsule *capsule); 52 | void dump_guest_calltrace(struct vcpu *vcpu); 53 | struct guest_mem *alloc_guest_mem(void); 54 | void free_guest_mem(struct guest_mem *mem); 55 | void track_alloc(struct capsule *capsule, struct page *page, 56 | enum guest_mem_type type); 57 | void alloc_guest_page(struct capsule *capsule, unsigned long gpa); 58 | 59 | void map_argv_envp(struct capsule *capsule); 60 | void map_exec_policies(struct capsule *capsule); 61 | 62 | void share_device_mem(struct capsule *capsule, unsigned long gpa); 63 | int resize_capsule_console(struct capsule *capsule, 64 | struct winsize *console_size); 65 | 66 | #endif /* HOST_MEMORY_H */ 67 | -------------------------------------------------------------------------------- /include/host/process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_PROCESS_H 18 | #define HOST_PROCESS_H 19 | 20 | #include 21 | 22 | #include "common/error.h" 23 | 24 | struct task_struct; 25 | 26 | err_t create_process_bitmap(struct task_struct *capsule_task); 27 | void free_process_bitmap(void); 28 | int keep_userland_process(struct task_struct *task); 29 | 30 | #endif /* _HOST_PROCESS_H */ 31 | -------------------------------------------------------------------------------- /include/host/segment.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _HOST_SEGMENT_H 18 | #define _HOST_SEGMENT_H 1 19 | 20 | enum segment_reg { 21 | ES, 22 | CS, 23 | SS, 24 | DS, 25 | FS, 26 | GS, 27 | LDTR, 28 | TR, 29 | NSEGREG, 30 | }; 31 | 32 | struct segment_access_rights { 33 | union { 34 | struct { 35 | unsigned type:4; 36 | unsigned s:1; 37 | unsigned dpl:2; 38 | unsigned present:1; 39 | unsigned reserved1:4; 40 | unsigned avl:1; 41 | unsigned l:1; 42 | unsigned db:1; 43 | unsigned g:1; 44 | unsigned unusable:1; 45 | unsigned reserved2:15; 46 | }; 47 | __u32 access; 48 | }; 49 | }; 50 | 51 | struct segment_selector { 52 | __u32 limit; 53 | __u64 base; 54 | }; 55 | 56 | struct vmcs_segment { 57 | __u16 selector; 58 | __u32 limit; 59 | __u32 ar_bytes; 60 | __u64 base; 61 | }; 62 | 63 | /* ugly gcc extension. */ 64 | #define SEGMENT_NAME(r) ({ \ 65 | char *p; \ 66 | switch (r) { \ 67 | case ES: p = "ES"; break; \ 68 | case CS: p = "CS"; break; \ 69 | case SS: p = "SS"; break; \ 70 | case DS: p = "DS"; break; \ 71 | case FS: p = "FS"; break; \ 72 | case GS: p = "GS"; break; \ 73 | case LDTR: p = "LDTR"; break; \ 74 | case TR: p = "TR"; break; \ 75 | default: p = "??"; break; \ 76 | } \ 77 | p; \ 78 | }) 79 | 80 | /* 45e876f794e8e566bf827c25ef0791875081724f 81 | * x86/segments/64: When loadsegment(fs, ...) fails, clear the base */ 82 | #ifndef __loadsegment_gs 83 | # define __loadsegment_gs(value) load_gs_index(value) 84 | #endif 85 | 86 | #ifndef loadsegment 87 | # define loadsegment(seg, value) __loadsegment(seg, value) 88 | #endif 89 | 90 | #endif /* _HOST_SEGMENT_H */ 91 | -------------------------------------------------------------------------------- /include/host/snapshot.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_SNAPSHOT_H 18 | #define HOST_SNAPSHOT_H 19 | 20 | #include 21 | 22 | #include "common/error.h" 23 | #include "common/snapshot_process.h" 24 | #include "host/context.h" 25 | #include "host/segment.h" 26 | 27 | 28 | #define MAX_PARAMS_NPAGES 5 29 | 30 | struct page_prot { 31 | unsigned char prot; 32 | }; 33 | 34 | struct snapshot { 35 | unsigned long cr3; 36 | unsigned long rip; 37 | unsigned long rflags; 38 | struct context ctx; 39 | struct vmcs_segment segs[NSEGREG]; 40 | 41 | int npages; 42 | unsigned long *orig_pfn; 43 | unsigned long *copy_pfn; 44 | pte_t *pte; 45 | 46 | unsigned long params_gpa[MAX_PARAMS_NPAGES]; 47 | unsigned long params_uaddr; 48 | unsigned int params_npages; 49 | 50 | struct snapshot_process process; 51 | }; 52 | 53 | extern struct snapshot snapshot; 54 | extern int snapshot_done; 55 | 56 | struct vcpu; 57 | 58 | void delete_snapshot(void); 59 | pte_t snapshot_gpa_to_hva(unsigned long gpa); 60 | err_t shrink_memory(void); 61 | err_t do_snapshot(struct vcpu *vcpu, unsigned long params_uaddr, 62 | unsigned int params_size); 63 | 64 | #endif /* HOST_SNAPSHOT_H */ 65 | -------------------------------------------------------------------------------- /include/host/symbols.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_SYMBOLS_H 18 | #define HOST_SYMBOLS_H 19 | 20 | #include "common/symbols.h" 21 | 22 | struct mm_struct; 23 | struct irq_chip; 24 | struct mm_walk; 25 | struct worker; 26 | 27 | extern struct mm_struct *_init_mm; 28 | extern struct list_head *_nosave_regions; 29 | extern int (*_is_vmalloc_or_module_addr)(const void *addr); 30 | extern struct pglist_data *(*_first_online_pgdat)(void); 31 | extern struct zone *(*_next_zone)(struct zone *zone); 32 | extern int (*_pfn_is_nosave)(unsigned long); 33 | extern unsigned long (*_shrink_all_memory)(unsigned long nr_pages); 34 | extern void (*_native_safe_halt)(void); 35 | extern void (*_vt_console_print)(void); 36 | extern int (*_walk_page_range)(unsigned long addr, unsigned long end, 37 | struct mm_walk *walk); 38 | extern void (*_schedule_tail)(struct task_struct *prev); 39 | extern int (*_sys_execve)(const char *filename, const char * const*__argv, 40 | const char * const*__envp); 41 | extern void (*_process_one_work)(struct worker *worker, struct work_struct *work); 42 | 43 | 44 | extern struct symbol symbols[]; 45 | extern struct per_cpu_symbol per_cpu_symbols[]; 46 | 47 | #endif /* HOST_SYMBOLS_H */ 48 | -------------------------------------------------------------------------------- /include/host/time.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_TIME_H 18 | #define HOST_TIME_H 19 | 20 | struct vcpu; 21 | 22 | void init_clock_timer(struct capsule *capsule); 23 | void vmcall_set_timer(struct vcpu *vcpu, __u64 nsec); 24 | void capsule_tsc_deadline(struct vcpu *vcpu, __u64 value); 25 | enum hrtimer_restart capsule_clock_event_function(struct capsule *capsule); 26 | 27 | #endif /* HOST_TIME_H */ 28 | -------------------------------------------------------------------------------- /include/host/transition.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _HOST_TRANSITION_H 18 | #define _HOST_TRANSITION_H 1 19 | 20 | struct capsule; 21 | struct vcpu; 22 | 23 | void force_shadow_process_fpu_usage(void); 24 | void switch_to_trusted(struct vcpu *vcpu); 25 | void switch_to_capsule(struct vcpu *vcpu, struct capsule *capsule); 26 | err_t load_trusted_vmcs(struct vcpu *vcpu); 27 | err_t load_capsule_vmcs(struct vcpu *vcpu, struct capsule *capsule); 28 | 29 | #endif /* _HOST_TRANSITION_H */ 30 | -------------------------------------------------------------------------------- /include/host/traps.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _HOST_TRAPS_H 18 | #define _HOST_TRAPS_H 1 19 | 20 | /* c94082656dac74257f63e91f78d5d458ac781fa5 21 | * x86: Use enum instead of literals for trap values 22 | * 2012-03-10! */ 23 | 24 | /* can't compare Ubuntu kernel versions: enum doesn't exist on 3.2.0-23 but 25 | * exists on 3.2.0-56 */ 26 | 27 | enum { 28 | X86_TRAP_DE = 0, /* 0, Divide-by-zero */ 29 | X86_TRAP_DB, /* 1, Debug */ 30 | X86_TRAP_NMI, /* 2, Non-maskable Interrupt */ 31 | X86_TRAP_BP, /* 3, Breakpoint */ 32 | X86_TRAP_OF, /* 4, Overflow */ 33 | X86_TRAP_BR, /* 5, Bound Range Exceeded */ 34 | X86_TRAP_UD, /* 6, Invalid Opcode */ 35 | X86_TRAP_NM, /* 7, Device Not Available */ 36 | X86_TRAP_DF, /* 8, Double Fault */ 37 | X86_TRAP_OLD_MF, /* 9, Coprocessor Segment Overrun */ 38 | X86_TRAP_TS, /* 10, Invalid TSS */ 39 | X86_TRAP_NP, /* 11, Segment Not Present */ 40 | X86_TRAP_SS, /* 12, Stack Segment Fault */ 41 | X86_TRAP_GP, /* 13, General Protection Fault */ 42 | X86_TRAP_PF, /* 14, Page Fault */ 43 | X86_TRAP_SPURIOUS, /* 15, Spurious Interrupt */ 44 | X86_TRAP_MF, /* 16, x87 Floating-Point Exception */ 45 | X86_TRAP_AC, /* 17, Alignment Check */ 46 | X86_TRAP_MC, /* 18, Machine Check */ 47 | X86_TRAP_XF, /* 19, SIMD Floating-Point Exception */ 48 | X86_TRAP_IRET = 32, /* 32, IRET Exception */ 49 | }; 50 | 51 | #endif /* _HOST_TRAPS_H */ 52 | -------------------------------------------------------------------------------- /include/host/vcpu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_VCPU_H 18 | #define HOST_VCPU_H 19 | 20 | #include "context.h" 21 | 22 | 23 | enum guest_type { 24 | GUEST_TRUSTED, 25 | GUEST_CAPSULE, 26 | }; 27 | 28 | struct vcpu { 29 | unsigned int cpu; 30 | bool bluepilled; 31 | bool stop_vmx; /* vmm is stopping, stop vmx */ 32 | struct regs regs; 33 | struct context trusted_ctx; 34 | enum guest_type guest; 35 | struct capsule *capsule; /* NULL if guest is not a capsule */ 36 | 37 | void *vmxon; 38 | void *vmm_stack; 39 | unsigned long guard_page; 40 | struct vmcs_region *vmcs_trusted; 41 | struct vmcs_template *trusted_template; 42 | }; 43 | 44 | #endif /* HOST_VCPU_H */ 45 | -------------------------------------------------------------------------------- /include/host/vm_exit.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _HOST_VM_EXIT_H 18 | #define _HOST_VM_EXIT_H 1 19 | 20 | void vm_exit_handler(void); 21 | 22 | #endif /* _HOST_VM_EXIT_H */ 23 | -------------------------------------------------------------------------------- /include/host/vmcs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _HOST_VMCS_H 18 | #define _HOST_VMCS_H 1 19 | 20 | struct ia32_vmx_basic_msr_bits { 21 | __u32 revid; 22 | unsigned region_size :12; 23 | unsigned RegionClear :1; 24 | unsigned Reserved1 :3; 25 | unsigned phy_addr_width :1; 26 | unsigned DualMon :1; 27 | unsigned mem_type :4; 28 | unsigned VmExitReport :1; 29 | unsigned Reserved2 :9; 30 | } __attribute__((__packed__)); 31 | 32 | union ia32_vmx_basic_msr { 33 | struct ia32_vmx_basic_msr_bits bits; 34 | __u64 value; 35 | }; 36 | 37 | struct vmcs_region; 38 | 39 | void init_vmcs_capsule_template(void); 40 | struct vmcs_template *alloc_vmcs_template(void); 41 | struct vmcs_region *alloc_vmcs(gfp_t flags); 42 | err_t init_trusted_vmcs(struct vmcs_region *vmcs, 43 | struct vmcs_template *tmpl, 44 | unsigned long host_rsp, 45 | struct vmx_msr_entry *autoload_msr, 46 | unsigned long guest_rip, 47 | unsigned long guest_rsp, 48 | unsigned long guest_rflags); 49 | err_t create_capsule_vmcs(struct vmcs_region **vmcs, 50 | struct vmcs_template *tmpl, 51 | unsigned long eptp, 52 | unsigned long guest_msr); 53 | int init_vmcs_bitmaps(void); 54 | void free_vmcs_bitmaps(void); 55 | 56 | #endif /* _HOST_VMCS_H */ 57 | -------------------------------------------------------------------------------- /include/host/vmm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_VMM_H 18 | #define HOST_VMM_H 19 | 20 | #include "cuapi/common/stats.h" 21 | 22 | #define VMM_STATS get_vmm_stats() 23 | 24 | struct vmm { 25 | struct vcpu *vcpus; 26 | unsigned int max_cpus; 27 | 28 | /* first vector that guest can used for xchan interrupt */ 29 | unsigned int xchan_first_vector; 30 | 31 | atomic_t pending_vmx_stop; 32 | 33 | atomic_t module_being_removed; 34 | 35 | int vpid_support; 36 | 37 | /* XXX: don't hardcode CPU limit. It should be dynamically allocated 38 | * like vcpus. */ 39 | struct vmm_stats stats[64]; 40 | }; 41 | 42 | extern struct vmm vmm; 43 | 44 | static __always_inline struct vmm_stats *get_vmm_stats(void) 45 | { 46 | unsigned int cpu; 47 | 48 | cpu = smp_processor_id(); 49 | if (cpu >= ARRAY_SIZE(vmm.stats)) { 50 | printk(KERN_ERR "hardcoded CPU limit reached while getting VMM stats\n"); 51 | cpu = 0; 52 | } 53 | 54 | return &vmm.stats[cpu]; 55 | } 56 | 57 | void cpu_disable_vmx(void *arg); 58 | 59 | #endif /* HOST_VMM_H */ 60 | -------------------------------------------------------------------------------- /include/host/vmx.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_VMX_H 18 | #define HOST_VMX_H 19 | 20 | #include "host/context.h" 21 | #include "host/vmm.h" 22 | #include "common/log.h" 23 | 24 | #define MSR_IA32_VMX_BASIC 0x00000480 25 | #define INVEPT_SINGLE_CONTEXT 1 26 | #define INVEPT_ALL_CONTEXT 2 27 | 28 | #define VMX_VPID_EXTENT_INDIVIDUAL_ADDR 0 29 | #define VMX_VPID_EXTENT_RETAIN_GLOBALS 3 30 | 31 | struct vmcs_region; 32 | 33 | void cpu_vmxerror_error(void); 34 | void cpu_vmwrite_error(unsigned long field, unsigned long value); 35 | void cpu_vmresume_failed(void); 36 | 37 | 38 | static __always_inline unsigned long cpu_vmcs_readl(unsigned long field) 39 | { 40 | unsigned long value; 41 | 42 | asm volatile ( 43 | ASM_VMX_VMREAD_RDX_RAX 44 | : "=a"(value) : "d"(field) : "cc" 45 | ); 46 | 47 | return value; 48 | } 49 | 50 | static __always_inline __u16 cpu_vmcs_read16(unsigned long field) 51 | { 52 | return cpu_vmcs_readl(field); 53 | } 54 | 55 | static __always_inline __u32 cpu_vmcs_read32(unsigned long field) 56 | { 57 | return cpu_vmcs_readl(field); 58 | } 59 | 60 | static __always_inline __u64 cpu_vmcs_read64(unsigned long field) 61 | { 62 | return cpu_vmcs_readl(field); 63 | } 64 | 65 | static __always_inline void cpu_vmcs_writel(unsigned long field, 66 | unsigned long value) 67 | { 68 | __u8 error; 69 | 70 | asm volatile ( 71 | ASM_VMX_VMWRITE_RAX_RDX "; setna %0" 72 | : "=q"(error) : "a"(value), "d"(field) : "cc" 73 | ); 74 | 75 | if (unlikely(error)) 76 | cpu_vmwrite_error(field, value); 77 | } 78 | 79 | static __always_inline void cpu_vmcs_write16(unsigned long field, __u16 value) 80 | { 81 | cpu_vmcs_writel(field, value); 82 | } 83 | 84 | static __always_inline void cpu_vmcs_write32(unsigned long field, __u32 value) 85 | { 86 | cpu_vmcs_writel(field, value); 87 | } 88 | 89 | static __always_inline void cpu_vmcs_write64(unsigned long field, __u64 value) 90 | { 91 | cpu_vmcs_writel(field, value); 92 | } 93 | 94 | static __always_inline int cpu_vmcs_load(struct vmcs_region *vmcs_region) 95 | { 96 | __u64 phys_addr = __pa(vmcs_region); 97 | __u8 error; 98 | 99 | asm volatile ( 100 | ASM_VMX_VMPTRLD_RAX "; setna %0" 101 | : "=qm"(error) : "a"(&phys_addr), "m"(phys_addr) 102 | : "cc", "memory" 103 | ); 104 | 105 | if (error) { 106 | printk(KERN_ERR "[virt] vmptrld %p/%llx failed\n", vmcs_region, 107 | phys_addr); 108 | return -1; 109 | } 110 | 111 | return 0; 112 | } 113 | 114 | static __always_inline int cpu_vmcs_clear(struct vmcs_region *vmcs_region) 115 | { 116 | __u64 phys_addr = __pa(vmcs_region); 117 | __u8 error; 118 | 119 | asm volatile ( 120 | ASM_VMX_VMCLEAR_RAX "; setna %0" 121 | : "=qm"(error) : "a"(&phys_addr), "m"(phys_addr) 122 | : "cc", "memory" 123 | ); 124 | 125 | if (error) { 126 | printk(KERN_ERR "[virt] vmclear fail: %p/%llx\n", vmcs_region, phys_addr); 127 | return -1; 128 | } 129 | 130 | return 0; 131 | } 132 | 133 | static __always_inline void cpu_vmx_resume(struct regs *regs) 134 | { 135 | __u8 error; 136 | 137 | asm volatile ( 138 | "mov %1, %%rcx\n" 139 | "mov %c[rax](%%rcx), %%rax\n" 140 | "mov %c[r15](%%rcx), %%r15\n" 141 | "mov %c[r14](%%rcx), %%r14\n" 142 | "mov %c[r13](%%rcx), %%r13\n" 143 | "mov %c[r12](%%rcx), %%r12\n" 144 | "mov %c[rbp](%%rcx), %%rbp\n" 145 | "mov %c[rbx](%%rcx), %%rbx\n" 146 | "mov %c[r11](%%rcx), %%r11\n" 147 | "mov %c[r10](%%rcx), %%r10\n" 148 | "mov %c[r9](%%rcx), %%r9\n" 149 | "mov %c[r8](%%rcx), %%r8\n" 150 | "mov %c[rdx](%%rcx), %%rdx\n" 151 | "mov %c[rsi](%%rcx), %%rsi\n" 152 | "mov %c[rdi](%%rcx), %%rdi\n" 153 | "mov %c[rcx](%%rcx), %%rcx\n" 154 | ASM_VMX_VMRESUME "\n" 155 | "setna %0" 156 | : "=q"(error) 157 | : "c"(regs), 158 | [rax]"i"(offsetof(struct regs, rax)), 159 | [rcx]"i"(offsetof(struct regs, rcx)), 160 | [rdx]"i"(offsetof(struct regs, rdx)), 161 | [rbx]"i"(offsetof(struct regs, rbx)), 162 | [rbp]"i"(offsetof(struct regs, rbp)), 163 | [rsi]"i"(offsetof(struct regs, rsi)), 164 | [rdi]"i"(offsetof(struct regs, rdi)), 165 | [r8]"i"(offsetof(struct regs, r8)), 166 | [r9]"i"(offsetof(struct regs, r9)), 167 | [r10]"i"(offsetof(struct regs, r10)), 168 | [r11]"i"(offsetof(struct regs, r11)), 169 | [r12]"i"(offsetof(struct regs, r12)), 170 | [r13]"i"(offsetof(struct regs, r13)), 171 | [r14]"i"(offsetof(struct regs, r14)), 172 | [r15]"i"(offsetof(struct regs, r15)) 173 | : "cc", "memory" 174 | ); 175 | 176 | /* never reached, except if vmresume failed */ 177 | cpu_vmresume_failed(); 178 | } 179 | 180 | static __always_inline int cpu_vmxon(void *vmxon_region) 181 | { 182 | __u64 phys_addr = __pa(vmxon_region); 183 | int ret; 184 | 185 | asm volatile ( 186 | ASM_VMX_VMXON_RAX "\n" 187 | "jc 1f\n" 188 | "xor %%rax, %%rax\n" 189 | "jmp 2f\n" 190 | "1:\n" 191 | "xor %%rax, %%rax\n" 192 | "dec %%rax\n" 193 | "2:\n" 194 | : "=a"(ret) : "a"(&phys_addr), "m"(phys_addr) 195 | : "memory", "cc" 196 | ); 197 | 198 | return ret; 199 | } 200 | 201 | static __always_inline void invept(int ext, __u64 eptp) 202 | { 203 | __u8 error, vmfailvalid, vmfailinvalid; 204 | struct { 205 | __u64 eptp; 206 | __u64 zero; 207 | } operand = { eptp, 0 }; 208 | 209 | asm volatile ( 210 | ASM_VMX_INVEPT "\n" 211 | "setbe %0\n" 212 | "setb %1\n" 213 | "sete %2\n" 214 | : "=qm"(error), "=qm"(vmfailinvalid), "=qm"(vmfailvalid) 215 | : "a" (&operand), "c" (ext) 216 | : "cc", "memory" 217 | ); 218 | 219 | if (error) { 220 | printk(KERN_ERR "invept %d failed (%d %d)\n", ext, 221 | vmfailinvalid, vmfailvalid); 222 | } 223 | } 224 | 225 | static inline void invvpid(int ext, u16 vpid, unsigned long gva) 226 | { 227 | __u8 error, vmfailvalid, vmfailinvalid; 228 | struct { 229 | __u64 vpid :16; 230 | __u64 rsvd :48; 231 | __u64 gva; 232 | } operand; 233 | 234 | /* one can argue this check should be done by the caller, but it's 235 | * easy to miss this check somewhere, and VPID is supported by every CPU 236 | * nowadays. */ 237 | if (!vmm.vpid_support) 238 | return; 239 | 240 | if (ext == VMX_VPID_EXTENT_INDIVIDUAL_ADDR) { 241 | /* even if caller is responsible of this, ensure that guest 242 | * linear address is canonical */ 243 | if ((((long)gva << 16) >> 16) != gva) { 244 | printk(KERN_ERR "BUG: invvpid: address is not canonical\n"); 245 | return; 246 | } 247 | } 248 | 249 | operand.vpid = vpid; 250 | operand.rsvd = 0; 251 | operand.gva = gva; 252 | 253 | asm volatile ( 254 | ASM_VMX_INVVPID "\n" 255 | "setbe %0\n" 256 | "setb %1\n" 257 | "sete %2\n" 258 | : "=qm"(error), "=qm"(vmfailinvalid), "=qm"(vmfailvalid) 259 | : "a"(&operand), "c"(ext) 260 | : "cc", "memory" 261 | ); 262 | 263 | if (error) { 264 | printk(KERN_ERR "invvpid %d failed (%d %d)\n", ext, 265 | vmfailinvalid, vmfailvalid); 266 | } 267 | } 268 | 269 | #endif /* HOST_VMX_H */ 270 | -------------------------------------------------------------------------------- /include/host/xchan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_XCHAN_H 18 | #define HOST_XCHAN_H 19 | 20 | #include "common/xchan.h" 21 | 22 | struct xchan { 23 | struct eventfd_ctx *events[XCHAN_TYPE_MAX]; 24 | }; 25 | 26 | struct vcpu; 27 | 28 | int xchan_set_event(unsigned int id, unsigned long arg1, struct eventfd_ctx *event); 29 | int xchan_notify_trusted(struct vcpu *vcpu, unsigned long arg0); 30 | void xchan_map_guest_page(struct vcpu *vcpu, unsigned long gpa, unsigned int n); 31 | void xchan_guest_closed(struct vcpu *vcpu, unsigned long arg0); 32 | 33 | #endif /* HOST_XCHAN_H */ 34 | -------------------------------------------------------------------------------- /include/shadow_process.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _SHADOW_PROCESS_H 18 | #define _SHADOW_PROCESS_H 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | #include "common/log.h" 25 | #include "cuapi/common/kill.h" 26 | #include "common/memory.h" 27 | 28 | struct daemon; 29 | 30 | struct shadow_process { 31 | bool woken_up; 32 | unsigned int capsule_id; 33 | struct task_struct *task; 34 | atomic_t timer_set; 35 | struct tasklet_struct tasklet; 36 | struct kref refcount; 37 | int capsule_killed; 38 | kill_t kill_reason; 39 | 40 | struct daemon *daemon; 41 | }; 42 | 43 | static inline void free_shadowp(struct kref *kref) 44 | { 45 | struct shadow_process *shadowp; 46 | unsigned int id; 47 | 48 | shadowp = container_of(kref, struct shadow_process, refcount); 49 | id = shadowp->capsule_id; 50 | poison(shadowp, 0x81, sizeof(*shadowp)); 51 | kfree(shadowp); 52 | 53 | cpsl_dbg(id, "shadowp freed"); 54 | } 55 | 56 | int shadow_process(void *arg); 57 | 58 | #endif /* _SHADOW_PROCESS_H */ 59 | -------------------------------------------------------------------------------- /include/trusted/channel.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef TRUSTED_CHANNEL_H 18 | #define TRUSTED_CHANNEL_H 19 | 20 | #include "common/error.h" 21 | #include "cuapi/common/kill.h" 22 | #include "cuapi/common/uuid.h" 23 | #include "cuapi/trusted/channel.h" 24 | 25 | struct capsule_params; 26 | struct daemon; 27 | 28 | err_t channel_init(void); 29 | void channel_exit(void); 30 | int channel_capsule_exited(struct daemon *daemon, unsigned int capsule_id, 31 | kill_t reason); 32 | err_t channel_create_capsule(void __user *u_params, 33 | struct capsule_params *params, 34 | unsigned int *result_capsule_id); 35 | long trusted_channel_ioctl(struct file *file, unsigned int cmd, 36 | unsigned long arg); 37 | 38 | #endif /* TRUSTED_CHANNEL_H */ 39 | -------------------------------------------------------------------------------- /include/trusted/fingerprint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _FINGERPRINT_H 18 | #define _FINGERPRINT_H 1 19 | 20 | #include "common/error.h" 21 | 22 | err_t check_breakpoints(void); 23 | 24 | #endif /* _FINGERPRINT_H */ 25 | -------------------------------------------------------------------------------- /include/trusted/mfn.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef HOST_MFN_H 18 | #define HOST_MFN_H 19 | 20 | #include "common/error.h" 21 | #include "cuapi/trusted/mfn.h" 22 | 23 | err_t host_mfn_init(void); 24 | void host_mfn_exit(void); 25 | 26 | #endif /* HOST_MFN_H */ 27 | -------------------------------------------------------------------------------- /include/trusted/time.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef _TRUSTED_TIME_H 18 | #define _TRUSTED_TIME_H 19 | 20 | enum hrtimer_restart trusted_clock_event_function(struct capsule *capsule); 21 | void tasklet_wake_up_shadowp(unsigned long arg); 22 | 23 | #endif /* _TRUSTED_TIME_H */ 24 | -------------------------------------------------------------------------------- /include/trusted/vmm.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef TRUSTED_VMM_H 18 | #define TRUSTED_VMM_H 19 | 20 | #include "common/error.h" 21 | 22 | struct vcpu; 23 | 24 | err_t cpu_enable_vmx(struct vcpu *vcpu); 25 | void kill_all_capsules(void); 26 | err_t init_vmm(void); 27 | void free_vmm(void); 28 | void stop_vmm(void); 29 | 30 | #endif /* TRUSTED_VMM_H */ 31 | -------------------------------------------------------------------------------- /include/trusted/xchan.h: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #ifndef TRUSTED_XCHAN_H 18 | #define TRUSTED_XCHAN_H 19 | 20 | #include "cuapi/trusted/xchan.h" 21 | #include "common/error.h" 22 | 23 | struct xchan_memory; 24 | 25 | void xchan_set_memory_id(struct xchan_memory *memory, unsigned int capsule_id); 26 | unsigned long xchan_get_memory_pages(struct xchan_memory *memory); 27 | err_t trusted_xchan_init(void); 28 | void trusted_xchan_exit(void); 29 | struct xchan_memory *xchan_alloc_pages(void); 30 | int xchan_put_pages(struct xchan_memory *memory); 31 | int xchan_put_pages_by_id(unsigned int id); 32 | err_t find_xchan_first_vector(void); 33 | 34 | #endif /* TRUSTED_XCHAN_H */ 35 | -------------------------------------------------------------------------------- /scripts/cappsule.lds: -------------------------------------------------------------------------------- 1 | /* 2 | * This script is used for cappsule.ko and cappsule-guest.ko. It would be 3 | * cleaner to have 2 separate scripts, because cappsule-guest.ko doesn't need 4 | * __start_* and __stop_* symbols. 5 | */ 6 | 7 | SECTIONS { 8 | /* allow kernel module to know .text section address and size */ 9 | PROVIDE(__start_erase_text = .); 10 | .text : { 11 | /* write .text section from every objects */ 12 | *(.text) 13 | 14 | /* Write .keep.common section from common/channel.o to the .text 15 | * section. It mustn't erased by the hypervisor.*/ 16 | PROVIDE(__start_keep_common = .); 17 | */common/channel.o (.keep.common) 18 | PROVIDE(__stop_keep_common = .); 19 | } 20 | PROVIDE(__stop_erase_text = .); 21 | } 22 | -------------------------------------------------------------------------------- /scripts/obf.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Obfuscate symbols used by a Linux kernel module. 4 | 5 | set -e 6 | readonly ARGS="$@" 7 | 8 | 9 | # get symbols from binary 10 | get_syms() 11 | { 12 | nm --debug-syms "$1" \ 13 | | grep -v '^ ' \ 14 | | cut -d ' ' -f 3 \ 15 | | sort -u 16 | } 17 | 18 | # don't rename symbols required by the Linux kernel 19 | filter_syms() 20 | { 21 | local pattern='' 22 | 23 | pattern+='^$' 24 | pattern+='\|__UNIQUE_ID_srcversion1\|__UNIQUE_ID_vermagic0' 25 | pattern+='\|__module_depends\|__this_module\|init_module\|cleanup_module' 26 | pattern+='\|____versions\|null' 27 | 28 | grep -v "$pattern" 29 | } 30 | 31 | # generate new symbols 32 | gen_map() 33 | { 34 | local mapfile=$1 35 | local i=0 36 | 37 | # reset map file 38 | echo -n '' > "$mapfile" 39 | 40 | while read sym; do 41 | printf "$sym s%x\n" $i >> "$mapfile" 42 | i=$((i+1)) 43 | done 44 | 45 | # sort map file for better readability 46 | sort --output="$mapfile" "$mapfile" 47 | } 48 | 49 | # replace symbols 50 | obfuscate() 51 | { 52 | local mapfile="$1" 53 | local infile="$2" 54 | 55 | objcopy --verbose --redefine-syms="$mapfile" "$infile" 56 | } 57 | 58 | main() 59 | { 60 | if [ $# -ne 2 ]; then 61 | echo "Usage: $0 " 62 | exit 1 63 | fi 64 | 65 | local filename="$1" 66 | local mapfile="$2" 67 | 68 | get_syms $filename \ 69 | | filter_syms \ 70 | | shuf \ 71 | | gen_map "$mapfile" 72 | 73 | obfuscate "$mapfile" "$filename" 74 | } 75 | 76 | main $ARGS 77 | -------------------------------------------------------------------------------- /trusted/asm.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | .code64 4 | 5 | ENTRY(shadow_process_fpu_used) 6 | fnop /* x87 floating-point instruction */ 7 | ret 8 | END(shadow_process_fpu_used) 9 | -------------------------------------------------------------------------------- /trusted/cappsule.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | 19 | #include "common/bluepill.h" 20 | #include "common/log.h" 21 | #include "common/error.h" 22 | #include "host/interrupt.h" 23 | #include "host/snapshot.h" 24 | #include "host/symbols.h" 25 | #include "host/vmm.h" 26 | #include "trusted/channel.h" 27 | #include "trusted/fingerprint.h" 28 | #include "trusted/mfn.h" 29 | #include "trusted/vmm.h" 30 | #include "trusted/xchan.h" 31 | 32 | MODULE_LICENSE("GPL"); 33 | MODULE_VERSION(VERSION); 34 | 35 | 36 | static int __init cappsule_init(void) 37 | { 38 | err_t error; 39 | 40 | error = log_init(); 41 | if (error != SUCCESS) 42 | goto out; 43 | 44 | error = resolve_symbols(symbols); 45 | if (error != SUCCESS) 46 | goto symbols_error; 47 | 48 | error = resolve_per_cpu_symbols(per_cpu_symbols); 49 | if (error != SUCCESS) 50 | goto symbols_error; 51 | 52 | error = check_breakpoints(); 53 | if (error != SUCCESS) 54 | goto symbols_error; 55 | 56 | error = channel_init(); 57 | if (error != SUCCESS) 58 | goto symbols_error; 59 | 60 | error = host_mfn_init(); 61 | if (error != SUCCESS) 62 | goto host_mfn_error; 63 | 64 | error = trusted_xchan_init(); 65 | if (error != SUCCESS) 66 | goto trusted_xchan_error; 67 | 68 | resolve_interrupt_handlers(); 69 | 70 | error = shrink_memory(); 71 | if (error != SUCCESS) 72 | goto shrink_memory_error; 73 | 74 | error = init_vmm(); 75 | if (error != SUCCESS) 76 | goto shrink_memory_error; 77 | 78 | error = bluepill(); 79 | if (error != SUCCESS) 80 | goto bluepill_error; 81 | 82 | snapshot_done = 0; 83 | 84 | return SUCCESS; 85 | 86 | bluepill_error: 87 | free_vmm(); 88 | shrink_memory_error: 89 | trusted_xchan_exit(); 90 | trusted_xchan_error: 91 | host_mfn_exit(); 92 | host_mfn_error: 93 | channel_exit(); 94 | symbols_error: 95 | log_exit(); 96 | out: 97 | /* errno is set to the value returned by the init function */ 98 | return -(CAPPSULE_ERRNO_BASE + error); 99 | } 100 | 101 | static void __exit cappsule_exit(void) 102 | { 103 | /* don't allow creation of new capsules */ 104 | atomic_set(&vmm.module_being_removed, 1); 105 | 106 | kill_all_capsules(); 107 | 108 | stop_vmm(); 109 | free_vmm(); 110 | 111 | delete_snapshot(); 112 | trusted_xchan_exit(); 113 | host_mfn_exit(); 114 | channel_exit(); 115 | log_exit(); 116 | } 117 | 118 | module_init(cappsule_init); 119 | module_exit(cappsule_exit); 120 | -------------------------------------------------------------------------------- /trusted/create_capsule.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "common/error.h" 21 | #include "shadow_process.h" 22 | #include "common/params.h" 23 | #include "common/vmcall.h" 24 | #include "host/snapshot.h" 25 | #include "trusted/channel.h" 26 | #include "trusted/xchan.h" 27 | 28 | 29 | err_t channel_create_capsule(void __user *u_params, 30 | struct capsule_params *params, 31 | unsigned int *result_capsule_id) 32 | { 33 | struct xchan_memory *xchan_memory; 34 | struct shadow_process *shadowp; 35 | struct task_struct *kthread; 36 | unsigned int id, random_cpu; 37 | void *info_pages; 38 | size_t size; 39 | err_t err; 40 | 41 | info_pages = NULL; 42 | shadowp = NULL; 43 | xchan_memory = NULL; 44 | 45 | if (!snapshot_done) { 46 | err = ERROR_CREATION_NO_SNAPSHOT; 47 | goto error; 48 | } 49 | 50 | size = snapshot.params_npages * PAGE_SIZE; 51 | info_pages = kmalloc(size, GFP_KERNEL); 52 | shadowp = kzalloc(sizeof(*shadowp), GFP_KERNEL); 53 | 54 | if (info_pages == NULL || shadowp == NULL) { 55 | err = ERROR_CREATION_ALLOC_FAILED; 56 | goto error; 57 | } 58 | 59 | if (copy_from_user(info_pages, u_params, size) != 0) { 60 | err = ERROR_CREATION_INVALID_USER_PAGES; 61 | goto error; 62 | } 63 | 64 | xchan_memory = xchan_alloc_pages(); 65 | if (xchan_memory == NULL) { 66 | err = ERROR_CREATION_XCHAN_ALLOC_FAILED; 67 | goto error; 68 | } 69 | 70 | params->info_pages = info_pages; 71 | params->xchan_pages = xchan_get_memory_pages(xchan_memory); 72 | 73 | /* create a kernel thread without starting it */ 74 | kthread = kthread_create(&shadow_process, (void *)shadowp, "capsule"); 75 | if (kthread == NULL) { 76 | err = ERROR_CREATION_KTHREAD_FAILED; 77 | goto error; 78 | } 79 | 80 | /* Bind shadow process to a random CPU. Use kthread_bind because 81 | * kthread_create_on_cpu isn't exported. */ 82 | random_cpu = smp_processor_id(); 83 | kthread_bind(kthread, random_cpu); 84 | 85 | /* create capsule structure and initialize shadowp */ 86 | shadowp->task = kthread; 87 | err = cpu_vmcs_vmcall3_ret(VMCALL_CREATE_CAPSULE, 88 | (long)params, (long)shadowp); 89 | if (err != SUCCESS) { 90 | /* kthread will exit without calling shadow_process */ 91 | kthread_stop(kthread); 92 | goto error; 93 | } 94 | 95 | id = shadowp->capsule_id; 96 | *result_capsule_id = id; 97 | 98 | /* once capsule id is known, kthread's name and xchan memory id can be 99 | * set */ 100 | snprintf(kthread->comm, sizeof(kthread->comm), "capsule-%u", id); 101 | xchan_set_memory_id(xchan_memory, id); 102 | 103 | /* start shadow process */ 104 | if (wake_up_process(kthread) != 1) 105 | tg_err("BUG: failed to wake shadow process (capsule: %d)", id); 106 | 107 | return SUCCESS; 108 | 109 | error: 110 | kfree(shadowp); 111 | kfree(info_pages); 112 | kfree(params); 113 | if (xchan_memory != NULL) 114 | xchan_put_pages(xchan_memory); 115 | return err; 116 | } 117 | -------------------------------------------------------------------------------- /trusted/exec_policy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "common/exec_policy.h" 22 | #include "common/log.h" 23 | 24 | 25 | /* check if pointer is out of policies pages */ 26 | static inline int out_of_bound(struct exec_policies *policies, void *p) 27 | { 28 | return ((char *)p >= (char *)policies + policies->size) || 29 | ((char *)p < (char *)policies); 30 | } 31 | 32 | /* check if policy is valid */ 33 | static int check_userland_policy(struct exec_policies *policies, 34 | struct exec_policy *policy) 35 | { 36 | char *end, *max_path, *path; 37 | unsigned int i, *offsets; 38 | int null_found; 39 | 40 | if (out_of_bound(policies, (char *)policy + sizeof(*policy))) { 41 | hv_err("%s: policy out of bound", __func__); 42 | return -1; 43 | } 44 | 45 | offsets = (unsigned int *)policy->data; 46 | if (out_of_bound(policies, offsets + policy->n)) { 47 | hv_err("%s: policy offsets out of bound", __func__); 48 | return -1; 49 | } 50 | 51 | max_path = NULL; 52 | for (i = 0; i < policy->n; i++) { 53 | path = policy->data + offsets[i]; 54 | if (out_of_bound(policies, path)) { 55 | hv_err("%s: path of policy out of bound", 56 | __func__); 57 | return -1; 58 | } 59 | if (path > max_path) 60 | max_path = path; 61 | } 62 | 63 | if (policy->n > 0) { 64 | null_found = 0; 65 | end = (char *)policies + policies->size; 66 | for (; max_path < end; max_path++) { 67 | if (*max_path == '\x00') { 68 | null_found = 1; 69 | break; 70 | } 71 | } 72 | 73 | if (!null_found) { 74 | hv_err("%s: paths aren't null terminated", __func__); 75 | return -1; 76 | } 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | /* check if policies are valid */ 83 | static int check_userland_policies(struct exec_policies *policies) 84 | { 85 | struct exec_policy *policy; 86 | unsigned int *offsets; 87 | unsigned int i; 88 | 89 | offsets = (unsigned int *)policies->data; 90 | if (out_of_bound(policies, offsets + policies->n)) { 91 | hv_err("%s: policies offsets out of bound", __func__); 92 | return -1; 93 | } 94 | 95 | for (i = 0; i < policies->n; i++) { 96 | policy = (struct exec_policy *)(policies->data + offsets[i]); 97 | if (check_userland_policy(policies, policy) != 0) 98 | return -1; 99 | } 100 | 101 | return 0; 102 | } 103 | 104 | void free_exec_policies(struct exec_policies *policies) 105 | { 106 | unsigned int order; 107 | 108 | order = get_order(policies->size); 109 | free_pages((unsigned long)policies, order); 110 | } 111 | 112 | struct exec_policies *copy_exec_policies(char __user *buf, size_t size) 113 | { 114 | struct exec_policies *policies; 115 | unsigned int order; 116 | unsigned long ret; 117 | 118 | /* add an additional page in case policies went to be modified */ 119 | order = get_order(size + PAGE_SIZE); 120 | policies = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, order); 121 | if (policies == NULL) 122 | return ERR_PTR(-ENOMEM); 123 | 124 | ret = copy_from_user(policies, buf, size); 125 | policies->size = size + PAGE_SIZE; 126 | if (ret != 0) { 127 | free_exec_policies(policies); 128 | return ERR_PTR(-EFAULT); 129 | } 130 | 131 | if (check_userland_policies(policies) != 0) { 132 | free_exec_policies(policies); 133 | return ERR_PTR(-EINVAL); 134 | } 135 | 136 | return policies; 137 | } 138 | -------------------------------------------------------------------------------- /trusted/fingerprint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "common/symbols.h" 22 | #include "common/log.h" 23 | #include "guest/symbols.h" 24 | #include "host/breakpoint.h" 25 | #include "host/symbols.h" 26 | #include "trusted/fingerprint.h" 27 | 28 | /* nop [rax+0+rax], eax */ 29 | #define NOP1 "\x0f\x1f\x44\x00\x00" 30 | /* nop */ 31 | #define NOP2 "\x66\x66\x66\x66\x90" 32 | 33 | 34 | /* because of paravirt, gcc appends 5 bytes at the beginning of every function 35 | * (verified on Linux ubuntu 3.11.0-17-generic #31~precise1-Ubuntu SMP Tue Feb 4 36 | * 21:25:43 UTC 2014 x86_64 GNU/Linux). */ 37 | #define FINGERPRINT(name, start) \ 38 | do { \ 39 | p = (unsigned char *)start; \ 40 | if (memcmp(p, NOP1, sizeof(NOP1)-1) != 0 && \ 41 | memcmp(p, NOP2, sizeof(NOP2)-1) != 0) { \ 42 | hv_err("%p %016lx", p, *(unsigned long *)p); \ 43 | hv_err("fingerprint failed: %d", __LINE__); \ 44 | return ERROR_CHECK_BREAKPOINTS; \ 45 | } \ 46 | bp_##name.addr = (unsigned long)p; \ 47 | } while (0) 48 | 49 | static bool is_pop_instruction(unsigned char *p, size_t size) 50 | { 51 | bool ret = false; 52 | 53 | if (size == 1) { 54 | if (*p >= 0x58 && *p <= 0x5e) 55 | ret = true; 56 | } else if (size == 2) { 57 | if (*p == 0x41 && (*(p+1) >= 0x58 && *(p+1) <= 0x5f)) 58 | ret = true; 59 | } 60 | 61 | return ret; 62 | } 63 | 64 | static unsigned long find_pop_ret(void *start) 65 | { 66 | unsigned char *p; 67 | 68 | for (p = (unsigned char *)start; ; p++) { 69 | if (*p == (unsigned char)INSTR_RET) { 70 | /* pop instruction is one or two bytes long */ 71 | if (is_pop_instruction(p-1, 1)) 72 | return (unsigned long)p; 73 | if (is_pop_instruction(p-2, 2)) 74 | return (unsigned long)p; 75 | } 76 | } 77 | 78 | return 0; 79 | } 80 | 81 | err_t check_breakpoints(void) 82 | { 83 | unsigned char *p; 84 | 85 | FINGERPRINT(do_exit, do_exit); 86 | FINGERPRINT(prepare_binprm, prepare_binprm); 87 | FINGERPRINT(vt_console_print, _vt_console_print); 88 | FINGERPRINT(process_one_work, _process_one_work); 89 | 90 | /* It's tempting to put a breakpoint at the function entry and modify 91 | * saved RIP in stack to call an additional function when it returns. 92 | * Unfortunately, some processes may be in the middle of __schedule() 93 | * during snapshot, and won't call the additional function when they 94 | * return. */ 95 | bp_schedule_end.addr = find_pop_ret(___schedule); 96 | bp_schedule_tail_end.addr = find_pop_ret(_schedule_tail); 97 | 98 | return SUCCESS; 99 | } 100 | -------------------------------------------------------------------------------- /trusted/mfn.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "common/error.h" 26 | #include "common/log.h" 27 | #include "common/mfn.h" 28 | #include "common/vmcall.h" 29 | #include "trusted/mfn.h" 30 | 31 | #define INVALID_CAPSULE_ID (~0) 32 | 33 | 34 | static int install_userland_mappings(unsigned int id, 35 | unsigned long __user *user_pfntable, 36 | unsigned long num_mfn, 37 | struct vm_area_struct *vma) 38 | { 39 | unsigned long addr, gpa, hva, pfn, ret; 40 | struct vmcall_gpa_hva_convert convert; 41 | unsigned long *pfntable, *hvatable; 42 | unsigned int i; 43 | size_t size; 44 | int err; 45 | 46 | if (vma->vm_flags & VM_WRITE) 47 | return -EINVAL; 48 | 49 | if (vma->vm_end - vma->vm_start != num_mfn * PAGE_SIZE) { 50 | cpsl_err(id, "%s: invalid size", __func__); 51 | return -EINVAL; 52 | } 53 | 54 | /* copy GPAs from userland */ 55 | pfntable = kmalloc_array(num_mfn, sizeof(*pfntable), GFP_KERNEL); 56 | if (pfntable == NULL) 57 | return -ENOMEM; 58 | 59 | size = sizeof(*pfntable) * num_mfn; 60 | if (copy_from_user(pfntable, user_pfntable, size) != 0) { 61 | kfree(pfntable); 62 | return -EFAULT; 63 | } 64 | 65 | for (i = 0; i < num_mfn; i++) { 66 | gpa = pfntable[i] << PAGE_SHIFT; 67 | pfntable[i] = gpa; 68 | } 69 | 70 | /* allocate an array for HVAs */ 71 | hvatable = kmalloc_array(num_mfn, sizeof(*hvatable), GFP_KERNEL); 72 | if (hvatable == NULL) { 73 | kfree(pfntable); 74 | return -ENOMEM; 75 | } 76 | 77 | /* get HVAs */ 78 | convert.capsule_id = id; 79 | convert.xorg_uid = __kuid_val(current_uid()); 80 | convert.num_mfn = num_mfn; 81 | convert.gpa = pfntable; 82 | convert.res_hva = hvatable; 83 | 84 | ret = cpu_vmcs_vmcall_ret(VMCALL_GPA_TO_HVA, (unsigned long)&convert); 85 | if (ret != 0) { 86 | kfree(pfntable); 87 | kfree(hvatable); 88 | return -EINVAL; 89 | } 90 | 91 | kfree(pfntable); 92 | 93 | /* no need to set vma->flags: remap_pfn_ranges() sets 94 | * VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP */ 95 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 96 | 97 | addr = vma->vm_start; 98 | err = 0; 99 | 100 | for (i = 0; i < num_mfn; i++) { 101 | hva = hvatable[i]; 102 | if (hva == 0) { 103 | tg_err("%s: guest address unmapped", __func__); 104 | err = -ENOENT; 105 | break; 106 | } 107 | 108 | //cpsl_dbg(capsule->id, "%s: %lx %ld", __func__, addr, pfn); 109 | pfn = __pa(hva) >> PAGE_SHIFT; 110 | err = remap_pfn_range(vma, addr, pfn, PAGE_SIZE, vma->vm_page_prot); 111 | if (err) { 112 | cpsl_err(id, "%s: remap_pfn_range failed %lx %ld: %d", 113 | __func__, addr, pfn, err); 114 | break; 115 | } 116 | 117 | addr += PAGE_SIZE; 118 | } 119 | 120 | /* XXX: remove mappings if error? */ 121 | 122 | kfree(hvatable); 123 | 124 | return err; 125 | } 126 | 127 | static int mmap(struct file *file, struct vm_area_struct *vma) 128 | { 129 | struct host_mfn *host_mfn; 130 | int ret; 131 | 132 | host_mfn = file->private_data; 133 | 134 | if (host_mfn->capsule_id == INVALID_CAPSULE_ID) { 135 | hv_err("%s: uninitialized capsule id", __func__); 136 | return -EINVAL; 137 | } 138 | 139 | ret = install_userland_mappings(host_mfn->capsule_id, 140 | host_mfn->user_pfntable, 141 | host_mfn->num_mfn, 142 | vma); 143 | 144 | return ret; 145 | } 146 | 147 | static ssize_t write(struct file *file, const char __user *in, 148 | size_t size, loff_t *off) 149 | { 150 | struct host_mfn *host_mfn, tmp; 151 | 152 | if (size != sizeof(tmp)) 153 | return -EINVAL; 154 | 155 | /* copy user data to a tmp structure to avoid incomplete copy */ 156 | if (copy_from_user(&tmp, in, size) != 0) 157 | return -EFAULT; 158 | 159 | host_mfn = file->private_data; 160 | *host_mfn = tmp; 161 | 162 | return size; 163 | } 164 | 165 | static const char *xorg_exe[] = { 166 | "/usr/lib/xorg/Xorg", 167 | "/usr/bin/Xorg", 168 | NULL 169 | }; 170 | 171 | /* Xorg is the only process allowed to access to this device. */ 172 | static bool is_program_allowed(void) 173 | { 174 | struct task_struct *task; 175 | struct file *exe_file; 176 | struct mm_struct *mm; 177 | const char **p; 178 | char buf[128]; 179 | char *path; 180 | 181 | task = get_current(); 182 | mm = get_task_mm(task); 183 | if (mm == NULL) 184 | return false; 185 | 186 | exe_file = get_mm_exe_file(mm); 187 | mmput(mm); 188 | if (exe_file == NULL) 189 | return false; 190 | 191 | path = d_path(&exe_file->f_path, buf, sizeof(buf)); 192 | fput(exe_file); 193 | 194 | if (IS_ERR(path)) 195 | return false; 196 | 197 | for (p = xorg_exe; *p != NULL; p++) { 198 | if (strcmp(*p, path) == 0) 199 | return true; 200 | } 201 | 202 | return false; 203 | } 204 | 205 | static int open(struct inode *inode, struct file *filp) 206 | { 207 | struct host_mfn *host_mfn; 208 | 209 | if (!is_program_allowed()) 210 | return -EPERM; 211 | 212 | host_mfn = kzalloc(sizeof(*host_mfn), GFP_KERNEL); 213 | if (host_mfn == NULL) 214 | return -ENOMEM; 215 | 216 | host_mfn->capsule_id = INVALID_CAPSULE_ID; 217 | filp->private_data = host_mfn; 218 | 219 | return 0; 220 | } 221 | 222 | static int close(struct inode *inode, struct file *file) 223 | { 224 | kfree(file->private_data); 225 | file->private_data = NULL; 226 | 227 | return 0; 228 | } 229 | 230 | static const struct file_operations mfn_fops = { 231 | .owner = THIS_MODULE, 232 | .open = open, 233 | .release = close, 234 | .write = write, 235 | .mmap = mmap, 236 | }; 237 | 238 | static struct miscdevice *mfn_dev; 239 | 240 | err_t host_mfn_init(void) 241 | { 242 | mfn_dev = kzalloc(sizeof(*mfn_dev), GFP_KERNEL); 243 | if (mfn_dev == NULL) 244 | return ERROR_ALLOC_FAILED; 245 | 246 | mfn_dev->minor = MISC_DYNAMIC_MINOR; 247 | mfn_dev->name = "capsule_mfn"; 248 | mfn_dev->fops = &mfn_fops; 249 | mfn_dev->mode = S_IRUGO | S_IWUGO; 250 | 251 | if (misc_register(mfn_dev) != 0) { 252 | kfree(mfn_dev); 253 | return ERROR_XCHAN_DEVICE_REGISTRATION; 254 | } 255 | 256 | return SUCCESS; 257 | } 258 | 259 | void host_mfn_exit(void) 260 | { 261 | misc_deregister(mfn_dev); 262 | kfree(mfn_dev); 263 | } 264 | -------------------------------------------------------------------------------- /trusted/shadowp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "shadow_process.h" 28 | #include "common/vmcall.h" 29 | #include "trusted/channel.h" 30 | #include "trusted/xchan.h" 31 | 32 | 33 | static int should_exit(struct shadow_process *shadowp) 34 | { 35 | if (shadowp->capsule_killed) { 36 | cpsl_info(shadowp->capsule_id, "shadow process: exit forced"); 37 | return 1; 38 | } 39 | 40 | /* SIGKILL and SIGTERM may be sent from userland */ 41 | if (signal_pending(current)) { 42 | cpsl_info(shadowp->capsule_id, "shadow process: got SIGKILL"); 43 | cpu_vmcs_vmcall(VMCALL_FATAL_SIGNAL, shadowp->capsule_id); 44 | return 1; 45 | } 46 | 47 | if (kthread_should_stop()) { 48 | cpsl_info(shadowp->capsule_id, "shadow process: should stop"); 49 | cpu_vmcs_vmcall(VMCALL_FATAL_SIGNAL, shadowp->capsule_id); 50 | return 1; 51 | } 52 | 53 | return 0; 54 | } 55 | 56 | /* executed in guest (trusted context) */ 57 | int shadow_process(void *arg) 58 | { 59 | struct shadow_process *shadowp; 60 | unsigned int id; 61 | int ret; 62 | 63 | shadowp = (struct shadow_process *)arg; 64 | shadowp->woken_up = true; 65 | id = shadowp->capsule_id; 66 | 67 | /* If capsule was killed, loop will break directly. If a fatal signal is 68 | * pending, capsule will be killed via a VMCALL in while loop. */ 69 | 70 | /* shadow process is bound to capsule CPU, thus vmcall is executed on 71 | * expected CPU */ 72 | cpu_vmcs_vmcall(VMCALL_LAUNCH_CAPSULE, id); 73 | 74 | /* allow kernel thread to receive these signals */ 75 | allow_signal(SIGKILL); 76 | allow_signal(SIGTERM); 77 | 78 | while (1) { 79 | if (should_exit(shadowp)) 80 | break; 81 | 82 | cpu_vmcs_vmcall(VMCALL_RESUME_EXECUTION, id); 83 | 84 | if (should_exit(shadowp)) 85 | break; 86 | 87 | if (atomic_read(&shadowp->timer_set)) { 88 | /* A timer is set, switch shadow process state from 89 | * TASK_RUNNING to TASK_INTERRUPTIBLE, and wait for 90 | * timer to expire. */ 91 | set_current_state(TASK_INTERRUPTIBLE); 92 | schedule(); 93 | } else { 94 | /* capsule reached its quantum, allow other processes in 95 | * trusted guest to execute */ 96 | schedule(); 97 | } 98 | } 99 | 100 | ret = channel_capsule_exited(shadowp->daemon, id, shadowp->kill_reason); 101 | if (ret != 0) 102 | cpsl_err(id, "failed to notify daemon of capsule exit"); 103 | 104 | /* shadow process mustn't use daemon anymore */ 105 | shadowp->daemon = NULL; 106 | 107 | if (id != shadowp->capsule_id) { 108 | cpsl_dbg(id, "registers where not correctly restored (%d)!", 109 | shadowp->capsule_id); 110 | return 0; 111 | } 112 | 113 | xchan_put_pages_by_id(id); 114 | 115 | tasklet_kill(&shadowp->tasklet); 116 | 117 | kref_put(&shadowp->refcount, free_shadowp); 118 | 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /trusted/time.c: -------------------------------------------------------------------------------- 1 | /* 2 | * (c) Copyright 2016 G. Campana 3 | * (c) Copyright 2016 Quarkslab 4 | * 5 | * This file is part of Cappsule. 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of version 2 of the GNU General Public License as 9 | * published by the Free Software Foundation. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | */ 16 | 17 | #include 18 | 19 | #include "shadow_process.h" 20 | #include "common/vmcall.h" 21 | #include "host/capsule.h" 22 | #include "trusted/time.h" 23 | 24 | 25 | /* A timer expired and capsule isn't running (trusted guest was interrupted). 26 | * Add pending interrupt to capsule and wake it up. */ 27 | enum hrtimer_restart trusted_clock_event_function(struct capsule *capsule) 28 | { 29 | ktime_t interval; 30 | 31 | /* if shadow process hasn't scheduled yet, restart timer */ 32 | if (current == capsule->shadowp->task) { 33 | interval = ns_to_ktime(100000); 34 | hrtimer_forward_now(&capsule->clock_timer, interval); 35 | return HRTIMER_RESTART; 36 | } 37 | 38 | cpu_vmcs_vmcall_ret(VMCALL_ADD_PENDING_TIMER_INTR, capsule->id); 39 | 40 | atomic_set(&capsule->shadowp->timer_set, 0); 41 | tasklet_schedule(&capsule->shadowp->tasklet); 42 | 43 | return HRTIMER_NORESTART; 44 | } 45 | 46 | void tasklet_wake_up_shadowp(unsigned long arg) 47 | { 48 | struct shadow_process *shadowp; 49 | 50 | shadowp = (struct shadow_process *)arg; 51 | wake_up_process(shadowp->task); 52 | } 53 | --------------------------------------------------------------------------------