1e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha/* sigsegv.c 2e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha * Copyright (c) 2012 The Chromium OS Authors. All rights reserved. 3e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha * Use of this source code is governed by a BSD-style license that can be 4e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha * found in the LICENSE file. 5e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha * 6e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha * Forces a denied system call to trigger a SIGSEGV at the instruction after 7e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha * the call using a SIGSYS handler.. This can be useful when debugging 8e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha * frameworks have trouble tracing through the SIGSYS handler. 9e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha * Proof of concept using amd64 registers and 'syscall'. 10e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha */ 11e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 12e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <asm/siginfo.h> 13e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define __have_siginfo_t 1 14e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define __have_sigval_t 1 15e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define __have_sigevent_t 1 16e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 17e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <linux/filter.h> 18e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <linux/prctl.h> 19e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <linux/seccomp.h> 20e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <limits.h> 21e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <stddef.h> 22e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <stdbool.h> 23e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <string.h> 24e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <syscall.h> 25e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define __USE_GNU 1 26e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <sys/ucontext.h> 27e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include <sys/mman.h> 28e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 29e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#include "test_harness.h" 30e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 31e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#ifndef PR_SET_NO_NEW_PRIVS 32e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define PR_SET_NO_NEW_PRIVS 38 33e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define PR_GET_NO_NEW_PRIVS 39 34e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#endif 35e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 36e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#if defined(__i386__) 37e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_IP REG_EIP 38e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_SP REG_ESP 39e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_RESULT REG_EAX 40e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_SYSCALL REG_EAX 41e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG0 REG_EBX 42e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG1 REG_ECX 43e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG2 REG_EDX 44e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG3 REG_ESI 45e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG4 REG_EDI 46e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG5 REG_EBP 47e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#elif defined(__x86_64__) 48e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_IP REG_RIP 49e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_SP REG_RSP 50e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_RESULT REG_RAX 51e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_SYSCALL REG_RAX 52e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG0 REG_RDI 53e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG1 REG_RSI 54e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG2 REG_RDX 55e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG3 REG_R10 56e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG4 REG_R8 57e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define REG_ARG5 REG_R9 58e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#endif 59e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 60e10f89421c169d4ab901d2853719375d74139ebdArun KulshreshthaFIXTURE_DATA(TRAP) { 61e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha struct sock_fprog prog; 62e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha}; 63e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 64e10f89421c169d4ab901d2853719375d74139ebdArun KulshreshthaFIXTURE_SETUP(TRAP) { 65e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha /* instruction after the syscall. Will be arch specific, of course. */ 66e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha { 67e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha struct sock_filter filter[] = { 68e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 69e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha offsetof(struct seccomp_data, nr)), 70e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha /* Whitelist anything you might need in the sigaction */ 71e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#ifdef __NR_sigreturn 72e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_sigreturn, 4, 0), 73e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#endif 74e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha /* TODO: only allow PROT_NONE */ 75e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_mprotect, 3, 0), 76e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_exit, 2, 0), 77e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_rt_sigreturn, 1, 0), 78e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha /* Allow __NR_write so easy logging. */ 79e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_write, 0, 1), 80e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), 81e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP), 82e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha }; 83e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha memset(&self->prog, 0, sizeof(self->prog)); 84e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha self->prog.filter = malloc(sizeof(filter)); 85e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ASSERT_NE(NULL, self->prog.filter); 86e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha memcpy(self->prog.filter, filter, sizeof(filter)); 87e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha self->prog.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])); 88e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha } 89e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha} 90e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 91e10f89421c169d4ab901d2853719375d74139ebdArun KulshreshthaFIXTURE_TEARDOWN(TRAP) { 92e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha if (self->prog.filter) 93e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha free(self->prog.filter); 94e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha}; 95e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 96e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshthastruct arch_sigsys { 97e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha void *_call_addr; /* calling user insn */ 98e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha int _syscall; /* triggering system call number */ 99e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha unsigned int _arch; /* AUDIT_ARCH_* of syscall */ 100e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha}; 101e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 102e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define _ALIGN(x,sz) (((x + ((sz)-1)) & ~((sz)-1)) - (sz)) 103e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#define ALIGN(x,sz) ((typeof(x))_ALIGN((unsigned long)(x),(unsigned long)(sz))) 104e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshthastatic long local_mprotect(void *target, unsigned long sz) 105e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha{ 106e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha register unsigned long res asm ("rax") = __NR_mprotect; 107e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha register void *addr asm ("rdi") = ALIGN(target, sz); 108e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha register long len asm ("rsi") = sz; 109e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha register long num asm ("rdx") = PROT_NONE; 110e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha __asm__("syscall\n"); 111e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha return res; 112e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha} 113e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 114e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshthastatic void TRAP_action(int nr, siginfo_t *info, void *void_context) 115e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha{ 116e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ucontext_t *ctx = (ucontext_t *)void_context; 117e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha char buf[256]; 118e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha int len; 119e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha int do_ret = 1; 120e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha struct arch_sigsys *sys = (struct arch_sigsys *) 121e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#ifdef si_syscall 122e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha &(info->si_call_addr); 123e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#else 124e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha &(info->si_pid); 125e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha#endif 126e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 127e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha if (info->si_code != SYS_SECCOMP) 128e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha return; 129e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha if (!ctx) 130e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha return; 131e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha len = snprintf(buf, sizeof(buf), 132e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha "@0x%lX:%X:%d:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX:0x%lX [0x%lX]\n", 133e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha (unsigned long)sys->_call_addr, 134e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha sys->_arch, 135e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha sys->_syscall, 136e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ctx->uc_mcontext.gregs[REG_ARG0], 137e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ctx->uc_mcontext.gregs[REG_ARG1], 138e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ctx->uc_mcontext.gregs[REG_ARG2], 139e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ctx->uc_mcontext.gregs[REG_ARG3], 140e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ctx->uc_mcontext.gregs[REG_ARG4], 141e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ctx->uc_mcontext.gregs[REG_ARG5], 142e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ALIGN(ctx->uc_mcontext.gregs[REG_IP], 4096)); 143e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha /* Emit some useful logs or whatever. */ 144e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha syscall(__NR_write, STDOUT_FILENO, buf, len); 145e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha /* Make the calling page non-exec */ 146e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha /* Careful on how it is called since it may make the syscall() instructions non-exec. */ 147e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha local_mprotect((void *)ctx->uc_mcontext.gregs[REG_IP], sysconf(_SC_PAGE_SIZE)); 148e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha} 149e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 150e10f89421c169d4ab901d2853719375d74139ebdArun KulshreshthaTEST_F_SIGNAL(TRAP, sigsegv, SIGSEGV) { 151e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha int ret; 152e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha struct sigaction act; 153e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha pid_t pid; 154e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha sigset_t mask; 155e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha memset(&act, 0, sizeof(act)); 156e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha sigemptyset(&mask); 157e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha sigaddset(&mask, SIGSYS); 158e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 159e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha act.sa_sigaction = &TRAP_action; 160e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha act.sa_flags = SA_SIGINFO; 161e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ret = sigaction(SIGSYS, &act, NULL); 162e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ASSERT_EQ(0, ret) { 163e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha TH_LOG("sigaction failed"); 164e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha } 165e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ret = sigprocmask(SIG_UNBLOCK, &mask, NULL); 166e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ASSERT_EQ(0, ret) { 167e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha TH_LOG("sigprocmask failed"); 168e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha } 169e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 170e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha /* Get the pid to compare against. */ 171e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha pid = getpid(); 172e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 173e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); 174e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ASSERT_EQ(0, ret); 175e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog); 176e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ASSERT_EQ(0, ret); 177e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 178e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha /* Call anything! */ 179e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha ret = syscall(__NR_getpid); 180e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha} 181e10f89421c169d4ab901d2853719375d74139ebdArun Kulshreshtha 182e10f89421c169d4ab901d2853719375d74139ebdArun KulshreshthaTEST_HARNESS_MAIN 183