1/* seccomp_bpf_tests.c 2 * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 * 6 * Test code for seccomp bpf. 7 */ 8 9#include <asm/siginfo.h> 10#define __have_siginfo_t 1 11#define __have_sigval_t 1 12#define __have_sigevent_t 1 13 14#include <linux/filter.h> 15#include <linux/prctl.h> 16#include <linux/seccomp.h> 17#include <stddef.h> 18#include <stdbool.h> 19#include <string.h> 20#include <syscall.h> 21#define __USE_GNU 1 22#include <sys/ucontext.h> 23#include <sys/mman.h> 24 25#include "test_harness.h" 26 27#ifndef PR_SET_NO_NEW_PRIVS 28#define PR_SET_NO_NEW_PRIVS 38 29#define PR_GET_NO_NEW_PRIVS 39 30#endif 31 32#if defined(__i386__) 33#define REG_IP REG_EIP 34#define REG_SP REG_ESP 35#define REG_RESULT REG_EAX 36#define REG_SYSCALL REG_EAX 37#define REG_ARG0 REG_EBX 38#define REG_ARG1 REG_ECX 39#define REG_ARG2 REG_EDX 40#define REG_ARG3 REG_ESI 41#define REG_ARG4 REG_EDI 42#define REG_ARG5 REG_EBP 43#elif defined(__x86_64__) 44#define REG_IP REG_RIP 45#define REG_SP REG_RSP 46#define REG_RESULT REG_RAX 47#define REG_SYSCALL REG_RAX 48#define REG_ARG0 REG_RDI 49#define REG_ARG1 REG_RSI 50#define REG_ARG2 REG_RDX 51#define REG_ARG3 REG_R10 52#define REG_ARG4 REG_R8 53#define REG_ARG5 REG_R9 54#endif 55 56FIXTURE_DATA(TRAP) { 57 struct sock_fprog prog; 58}; 59 60/* XXX: will need one per arch, etc. 61 * thankfully _arch can tell us the calling convention! 62 */ 63extern void *thunk_ip; /* label for the instruction _after_ syscall */ 64static void syscall_thunk(void) 65{ 66 asm("syscall; thunk_ip:"); 67} 68 69static time_t vsyscall_time(time_t *p) 70{ 71 register time_t t asm ("rax"); 72 register time_t *p1 asm ("rdi") = p; 73 __asm__("call 0xffffffffff600400 \n"); 74 return t; 75} 76 77 78#if 0 79/* For instance, we could jump here instead. */ 80static void compat_thunk(void) 81{ 82 asm("int 0x80"); 83} 84#endif 85 86FIXTURE_SETUP(TRAP) { 87 /* instruction after the syscall. Will be arch specific, of course. */ 88 unsigned long thunk_addr = (unsigned long)&thunk_ip; 89 TH_LOG("Thunk: 0x%lX\n", thunk_addr); 90 { 91 struct sock_filter filter[] = { 92 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 93 offsetof(struct seccomp_data, nr)), 94 /* Whitelist anything you might need in the sigaction */ 95#ifdef __NR_sigreturn 96 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 3, 0), 97#endif 98 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 2, 0), 99 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 1, 0), 100 /* Allow __NR_write so easy logging. */ 101 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 0, 1), 102 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), 103 /* Check if we're within the thunk. */ 104 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 105 offsetof(struct seccomp_data, instruction_pointer)), 106 /* XXX: make this 32-bit friendly. */ 107 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ((__u32*)&thunk_addr)[0], 0, 3), 108 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 109 offsetof(struct seccomp_data, instruction_pointer)+sizeof(int)), 110 BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ((__u32*)&thunk_addr)[1], 0, 1), 111 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), 112 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP), 113 }; 114 memset(&self->prog, 0, sizeof(self->prog)); 115 self->prog.filter = malloc(sizeof(filter)); 116 ASSERT_NE(NULL, self->prog.filter); 117 memcpy(self->prog.filter, filter, sizeof(filter)); 118 self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])); 119 } 120} 121 122FIXTURE_TEARDOWN(TRAP) { 123 if (self->prog.filter) 124 free(self->prog.filter); 125}; 126 127struct arch_sigsys { 128 void *_call_addr; /* calling user insn */ 129 int _syscall; /* triggering system call number */ 130 unsigned int _arch; /* AUDIT_ARCH_* of syscall */ 131}; 132 133static void TRAP_action(int nr, siginfo_t *info, void *void_context) 134{ 135 ucontext_t *ctx = (ucontext_t *)void_context; 136 char buf[256]; 137 int len; 138 int do_ret = 1; 139 struct arch_sigsys *sys = (struct arch_sigsys *) 140#ifdef si_syscall 141 &(info->si_call_addr); 142#else 143 &(info->si_pid); 144#endif 145 146 if (info->si_code != SYS_SECCOMP) 147 return; 148 if (!ctx) 149 return; 150 len = snprintf(buf, sizeof(buf), 151 "@0x%lX:%X:%d:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX\n", 152 (unsigned long)sys->_call_addr, 153 sys->_arch, 154 sys->_syscall, 155 ctx->uc_mcontext.gregs[REG_ARG0], 156 ctx->uc_mcontext.gregs[REG_ARG1], 157 ctx->uc_mcontext.gregs[REG_ARG2], 158 ctx->uc_mcontext.gregs[REG_ARG3], 159 ctx->uc_mcontext.gregs[REG_ARG4], 160 ctx->uc_mcontext.gregs[REG_ARG5]); 161 /* Send the soft-fail to our "listener" */ 162 syscall(__NR_write, STDOUT_FILENO, buf, len); 163 if (ctx->uc_mcontext.gregs[REG_IP] >= 0xffffffffff600000ULL && 164 ctx->uc_mcontext.gregs[REG_IP] < 0xffffffffff601000ULL) 165 do_ret = 0; 166 if (do_ret) { 167 /* push [REG_IP] */ 168 ctx->uc_mcontext.gregs[REG_SP] -= sizeof(unsigned long); 169 *((unsigned long *)ctx->uc_mcontext.gregs[REG_SP]) = 170 ctx->uc_mcontext.gregs[REG_IP]; 171 } 172 /* jmp syscall_thunk */ 173 ctx->uc_mcontext.gregs[REG_IP] = (unsigned long)syscall_thunk; 174 return; 175} 176 177TEST_F(TRAP, handler) { 178 int ret; 179 struct sigaction act; 180 pid_t pid; 181 sigset_t mask; 182 memset(&act, 0, sizeof(act)); 183 sigemptyset(&mask); 184 sigaddset(&mask, SIGSYS); 185 186 act.sa_sigaction = &TRAP_action; 187 act.sa_flags = SA_SIGINFO; 188 ret = sigaction(SIGSYS, &act, NULL); 189 ASSERT_EQ(0, ret) { 190 TH_LOG("sigaction failed"); 191 } 192 ret = sigprocmask(SIG_UNBLOCK, &mask, NULL); 193 ASSERT_EQ(0, ret) { 194 TH_LOG("sigprocmask failed"); 195 } 196 197 /* Get the pid to compare against. */ 198 pid = getpid(); 199 200 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 201 ASSERT_EQ(0, ret); 202 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog); 203 ASSERT_EQ(0, ret); 204 205 /* Call anything! */ 206 ret = syscall(__NR_getpid); 207 ASSERT_EQ(pid, ret); 208 ret = syscall(__NR_close, 0); 209 ASSERT_EQ(0, ret); 210 ret = syscall(__NR_close, 0); 211 ASSERT_EQ(-1, ret); 212 printf("The time is %ld\n", vsyscall_time(NULL)); 213 ASSERT_LT(0, vsyscall_time(NULL)); 214} 215 216TEST_HARNESS_MAIN 217