#define _GNU_SOURCE #include #include #include #include #include #include #include #include #ifndef __ARM_EABI__ #error Must be compiled for ARM EABI #endif struct seccomp_data { int nr; __u32 arch; __u64 instruction_pointer; __u64 args[6]; }; #ifndef PR_SET_NO_NEW_PRIVS #define PR_SET_NO_NEW_PRIVS 38 #endif #define SECCOMP_RET_KILL 0x00000000U #define SECCOMP_RET_TRAP 0x00030000U #define SECCOMP_RET_ERRNO 0x00050000U #define SECCOMP_RET_TRACE 0x7ff00000U #define SECCOMP_RET_ALLOW 0x7fff0000U struct sifields_sigsys { void *_call_addr; int _syscall; unsigned int _arch; }; #define SIGINFO_SIGSYS(si) ((struct sifields_sigsys *)&(si)->_sifields) __attribute__((noinline,optimize("2"))) long call_getgid_oabi(void) { // If OABI compatibility is disabled, this will call exit instead // (That's what r7==1 means.) register long ret asm("r0"); asm volatile("mov r0, $1\n\tmov r1, $2\n\tmov r2, $3\n\t" "mov r3, $4\n\tmov r4, $5\n\tmov r5, $6\n\t" "mov r7, $1\n\tsvc $0x90002f\n\t" : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "memory"); return ret; } void handler(int signum, siginfo_t *si, void *uc_void) { const struct ucontext *uc = uc_void; const struct sifields_sigsys *ss = SIGINFO_SIGSYS(si); printf("SIGSYS\n\n"); printf("nr: 0x%X (__NR_getgid = 0x%X, OABI nr = 0x90002F)\n", ss->_syscall, __NR_getgid); #define DO_REG(i) printf("r" #i ": 0x%08X\n", uc->uc_mcontext.arm_r##i); DO_REG(0); DO_REG(1); DO_REG(2); DO_REG(3); DO_REG(4); DO_REG(5); DO_REG(6); DO_REG(7); } int main() { int rc; struct sock_filter filter[] = { BPF_STMT(BPF_LD+BPF_W+BPF_ABS, (offsetof(struct seccomp_data, nr))), BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_getgid, 0, 1), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP), BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), }; struct sock_fprog prog = { .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])), .filter = filter, }; struct sigaction sa = {}; sa.sa_sigaction = handler; sa.sa_flags = SA_SIGINFO; if (sigaction(SIGSYS, &sa, NULL) != 0) err(1, "sigaction"); if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) err(1, "PR_SET_NO_NEW_PRIVS"); if (prctl(PR_SET_SECCOMP, 2, &prog)) err(1, "PR_SET_SECCOMP"); call_getgid_oabi(); return 0; }