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 .count = 0, 30 }; 31 static const char msg1[] = "Please type something: "; 32 static const char msg2[] = "You typed: "; 33 char buf[256]; 34 struct sock_filter filter[] = { 35 /* TODO: LOAD_SYSCALL_NR(arch) and enforce an arch */ 36 LOAD_SYSCALL_NR, 37 SYSCALL(__NR_exit, ALLOW), 38 SYSCALL(__NR_exit_group, ALLOW), 39 SYSCALL(__NR_write, JUMP(&l, write_fd)), 40 SYSCALL(__NR_read, JUMP(&l, read)), 41 DENY, /* Don't passthrough into a label */ 42 43 LABEL(&l, read), 44 ARG(0), 45 JNE(STDIN_FILENO, DENY), 46 ARG(1), 47 JNE((unsigned long)buf, DENY), 48 ARG(2), 49 JGE(sizeof(buf), DENY), 50 ALLOW, 51 52 LABEL(&l, write_fd), 53 ARG(0), 54 JEQ(STDOUT_FILENO, JUMP(&l, write_buf)), 55 JEQ(STDERR_FILENO, JUMP(&l, write_buf)), 56 DENY, 57 58 LABEL(&l, write_buf), 59 ARG(1), 60 JEQ((unsigned long)msg1, JUMP(&l, msg1_len)), 61 JEQ((unsigned long)msg2, JUMP(&l, msg2_len)), 62 JEQ((unsigned long)buf, JUMP(&l, buf_len)), 63 DENY, 64 65 LABEL(&l, msg1_len), 66 ARG(2), 67 JLT(sizeof(msg1), ALLOW), 68 DENY, 69 70 LABEL(&l, msg2_len), 71 ARG(2), 72 JLT(sizeof(msg2), ALLOW), 73 DENY, 74 75 LABEL(&l, buf_len), 76 ARG(2), 77 JLT(sizeof(buf), ALLOW), 78 DENY, 79 }; 80 struct sock_fprog prog = { 81 .filter = filter, 82 .len = (unsigned short)(sizeof(filter)/sizeof(filter[0])), 83 }; 84 ssize_t bytes; 85 bpf_resolve_jumps(&l, filter, sizeof(filter)/sizeof(*filter)); 86 87 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { 88 perror("prctl(NO_NEW_PRIVS)"); 89 return 1; 90 } 91 92 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { 93 perror("prctl(SECCOMP)"); 94 return 1; 95 } 96 syscall(__NR_write, STDOUT_FILENO, msg1, strlen(msg1)); 97 bytes = syscall(__NR_read, STDIN_FILENO, buf, sizeof(buf)-1); 98 bytes = (bytes > 0 ? bytes : 0); 99 syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)); 100 syscall(__NR_write, STDERR_FILENO, buf, bytes); 101 /* Now get killed */ 102 syscall(__NR_write, STDERR_FILENO, msg2, strlen(msg2)+2); 103 return 0; 104 } 105