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