1 /* 2 * Seccomp BPF example using a macro-based generator. 3 * 4 * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org> 5 * Author: Will Drewry <wad@chromium.org> 6 * 7 * The code may be used by anyone for any purpose, 8 * and can serve as a starting point for developing 9 * applications using prctl(PR_ATTACH_SECCOMP_FILTER). 10 */ 11 12 #include <linux/filter.h> 13 #include <linux/seccomp.h> 14 #include <linux/unistd.h> 15 #include <stdio.h> 16 #include <string.h> 17 #include <sys/prctl.h> 18 #include <unistd.h> 19 20 #include "bpf-helper.h" 21 22 #ifndef PR_SET_NO_NEW_PRIVS 23 #define PR_SET_NO_NEW_PRIVS 38 24 #endif 25 26 int main(int argc, char **argv) 27 { 28 struct bpf_labels l; 29 static const char msg1[] = "Please type something: "; 30 static const char msg2[] = "You typed: "; 31 char buf[256]; 32 struct sock_filter filter[] = { 33 /* TODO: LOAD_SYSCALL_NR(arch) and enforce an arch */ 34 LOAD_SYSCALL_NR, 35 SYSCALL(__NR_exit, ALLOW), 36 SYSCALL(__NR_exit_group, ALLOW), 37 SYSCALL(__NR_write, JUMP(&l, write_fd)), 38 SYSCALL(__NR_read, JUMP(&l, read)), 39 DENY, /* Don't passthrough into a label */ 40 41 LABEL(&l, read), 42 ARG(0), 43 JNE(STDIN_FILENO, DENY), 44 ARG(1), 45 JNE((unsigned long)buf, DENY), 46 ARG(2), 47 JGE(sizeof(buf), DENY), 48 ALLOW, 49 50 LABEL(&l, write_fd), 51 ARG(0), 52 JEQ(STDOUT_FILENO, JUMP(&l, write_buf)), 53 JEQ(STDERR_FILENO, JUMP(&l, write_buf)), 54 DENY, 55 56 LABEL(&l, write_buf), 57 ARG(1), 58 JEQ((unsigned long)msg1, JUMP(&l, msg1_len)), 59 JEQ((unsigned long)msg2, JUMP(&l, msg2_len)), 60 JEQ((unsigned long)buf, JUMP(&l, buf_len)), 61 DENY, 62 63 LABEL(&l, msg1_len), 64 ARG(2), 65 JLT(sizeof(msg1), ALLOW), 66 DENY, 67 68 LABEL(&l, msg2_len), 69 ARG(2), 70 JLT(sizeof(msg2), ALLOW), 71 DENY, 72 73 LABEL(&l, buf_len), 74 ARG(2), 75 JLT(sizeof(buf), ALLOW), 76 DENY, 77 }; 78 struct sock_fprog prog = { 79 .filter = filter, 80 .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])), 81 }; 82 ssize_t bytes; 83 bpf_resolve_jumps(&l, filter, sizeof(filter)/sizeof(*filter)); 84 85 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 86 perror("prctl(NO_NEW_PRIVS)"); 87 return 1; 88 } 89 90 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { 91 perror("prctl(SECCOMP)"); 92 return 1; 93 } 94 syscall(__NR_write, STDOUT_FILENO, msg1, strlen(msg1)); 95 bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf)-1); 96 bytes = (bytes > 0 ? bytes : 0); 97 syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)); 98 syscall(__NR_write, STDERR_FILENO, buf, bytes); 99 /* Now get killed */ 100 syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)+2); 101 return 0; 102 } 103