1 #ifdef HAVE_CONFIG_H 2 # include "config.h" 3 #endif 4 5 #include <stddef.h> 6 #include <unistd.h> 7 #include <stdio.h> 8 #include <errno.h> 9 #include <sys/syscall.h> 10 11 #ifdef HAVE_PRCTL 12 # include <sys/prctl.h> 13 #endif 14 #ifdef HAVE_LINUX_SECCOMP_H 15 # include <linux/seccomp.h> 16 #endif 17 #ifdef HAVE_LINUX_FILTER_H 18 # include <linux/filter.h> 19 #endif 20 21 #if defined HAVE_PRCTL \ 22 && defined PR_SET_NO_NEW_PRIVS \ 23 && defined PR_SET_SECCOMP \ 24 && defined SECCOMP_MODE_FILTER \ 25 && defined SECCOMP_RET_ERRNO \ 26 && defined BPF_JUMP \ 27 && defined BPF_STMT 28 29 #define SOCK_FILTER_ALLOW_SYSCALL(nr) \ 30 BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, __NR_ ## nr, 0, 1), \ 31 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW) 32 33 #define SOCK_FILTER_DENY_SYSCALL(nr, err) \ 34 BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, __NR_ ## nr, 0, 1), \ 35 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (SECCOMP_RET_DATA & (err))) 36 37 #define SOCK_FILTER_KILL_PROCESS \ 38 BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL) 39 40 #define PRINT_ALLOW_SYSCALL(nr) \ 41 printf("BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, %#x, 0, 0x1), " \ 42 "BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW), ", \ 43 __NR_ ## nr) 44 45 #define PRINT_DENY_SYSCALL(nr, err) \ 46 printf("BPF_JUMP(BPF_JMP | BPF_K | BPF_JEQ, %#x, 0, 0x1), " \ 47 "BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | %#x), ", \ 48 __NR_ ## nr, err) 49 50 static const struct sock_filter filter[] = { 51 /* load syscall number */ 52 BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)), 53 54 /* allow syscalls */ 55 SOCK_FILTER_ALLOW_SYSCALL(close), 56 SOCK_FILTER_ALLOW_SYSCALL(exit), 57 SOCK_FILTER_ALLOW_SYSCALL(exit_group), 58 59 /* deny syscalls */ 60 SOCK_FILTER_DENY_SYSCALL(sync, EBUSY), 61 SOCK_FILTER_DENY_SYSCALL(setsid, EPERM), 62 63 /* kill process */ 64 SOCK_FILTER_KILL_PROCESS 65 }; 66 67 static const struct sock_fprog prog = { 68 .len = sizeof(filter) / sizeof(filter[0]), 69 .filter = (struct sock_filter *) filter, 70 }; 71 72 int 73 main(void) 74 { 75 int fds[2]; 76 77 puts("prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) = 0"); 78 79 printf("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, ["); 80 81 printf("BPF_STMT(BPF_LD | BPF_W | BPF_ABS, %#x), ", 82 (unsigned) offsetof(struct seccomp_data, nr)); 83 84 PRINT_ALLOW_SYSCALL(close); 85 PRINT_ALLOW_SYSCALL(exit); 86 PRINT_ALLOW_SYSCALL(exit_group); 87 88 PRINT_DENY_SYSCALL(sync, EBUSY), 89 PRINT_DENY_SYSCALL(setsid, EPERM), 90 91 printf("BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL)"); 92 93 puts("]) = 0"); 94 puts("+++ exited with 0 +++"); 95 96 fflush(stdout); 97 close(0); 98 close(1); 99 100 if (pipe(fds) || 101 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) || 102 prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) || 103 close(0) || close(1)) 104 _exit(77); 105 106 _exit(0); 107 } 108 109 #else 110 111 int main(void) { return 77; } 112 113 #endif 114