1 /* 2 * Check verbose decoding of prctl PR_SET_SECCOMP SECCOMP_MODE_FILTER. 3 * 4 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org> 5 * Copyright (c) 2016-2017 The strace developers. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "tests.h" 32 #include <stddef.h> 33 #include <unistd.h> 34 #include <stdio.h> 35 #include <errno.h> 36 #include <asm/unistd.h> 37 38 #ifdef HAVE_PRCTL 39 # include <sys/prctl.h> 40 #endif 41 #ifdef HAVE_LINUX_SECCOMP_H 42 # include <linux/seccomp.h> 43 #endif 44 #include <linux/filter.h> 45 46 #if defined HAVE_PRCTL \ 47 && defined PR_SET_NO_NEW_PRIVS \ 48 && defined PR_SET_SECCOMP \ 49 && defined SECCOMP_MODE_FILTER \ 50 && defined SECCOMP_RET_ERRNO \ 51 && defined BPF_JUMP \ 52 && defined BPF_STMT 53 54 #define SOCK_FILTER_ALLOW_SYSCALL(nr) \ 55 BPF_JUMP(BPF_JMP|BPF_K|BPF_JEQ, __NR_ ## nr, 0, 1), \ 56 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW) 57 58 #define SOCK_FILTER_DENY_SYSCALL(nr, err) \ 59 BPF_JUMP(BPF_JMP|BPF_K|BPF_JEQ, __NR_ ## nr, 0, 1), \ 60 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO|(SECCOMP_RET_DATA & (err))) 61 62 #define SOCK_FILTER_KILL_PROCESS \ 63 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL) 64 65 #define PRINT_ALLOW_SYSCALL(nr) \ 66 printf("BPF_JUMP(BPF_JMP|BPF_K|BPF_JEQ, %#x, 0, 0x1), " \ 67 "BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW), ", \ 68 __NR_ ## nr) 69 70 #define PRINT_DENY_SYSCALL(nr, err) \ 71 printf("BPF_JUMP(BPF_JMP|BPF_K|BPF_JEQ, %#x, 0, 0x1), " \ 72 "BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO|%#x), ", \ 73 __NR_ ## nr, err) 74 75 static const struct sock_filter filter[] = { 76 /* load syscall number */ 77 BPF_STMT(BPF_LD|BPF_W|BPF_ABS, offsetof(struct seccomp_data, nr)), 78 79 /* allow syscalls */ 80 SOCK_FILTER_ALLOW_SYSCALL(close), 81 SOCK_FILTER_ALLOW_SYSCALL(exit), 82 SOCK_FILTER_ALLOW_SYSCALL(exit_group), 83 84 /* deny syscalls */ 85 SOCK_FILTER_DENY_SYSCALL(sync, EBUSY), 86 SOCK_FILTER_DENY_SYSCALL(setsid, EPERM), 87 88 /* kill process */ 89 SOCK_FILTER_KILL_PROCESS 90 }; 91 92 static const struct sock_fprog prog = { 93 .len = ARRAY_SIZE(filter), 94 .filter = (struct sock_filter *) filter, 95 }; 96 97 int 98 main(void) 99 { 100 int fds[2]; 101 102 puts("prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) = 0"); 103 104 printf("prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, {len=%u, filter=[", 105 prog.len); 106 107 printf("BPF_STMT(BPF_LD|BPF_W|BPF_ABS, %#x), ", 108 (unsigned) offsetof(struct seccomp_data, nr)); 109 110 PRINT_ALLOW_SYSCALL(close); 111 PRINT_ALLOW_SYSCALL(exit); 112 PRINT_ALLOW_SYSCALL(exit_group); 113 114 PRINT_DENY_SYSCALL(sync, EBUSY), 115 PRINT_DENY_SYSCALL(setsid, EPERM), 116 117 printf("BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL_THREAD)"); 118 119 puts("]}) = 0"); 120 puts("+++ exited with 0 +++"); 121 122 fflush(stdout); 123 close(0); 124 close(1); 125 126 if (pipe(fds)) 127 perror_msg_and_fail("pipe"); 128 if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) 129 perror_msg_and_skip("PR_SET_NO_NEW_PRIVS"); 130 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) 131 perror_msg_and_skip("PR_SET_SECCOMP"); 132 if (close(0) || close(1)) 133 _exit(77); 134 135 _exit(0); 136 } 137 138 #else 139 140 SKIP_MAIN_UNDEFINED("HAVE_PRCTL && PR_SET_NO_NEW_PRIVS && PR_SET_SECCOMP" 141 " && SECCOMP_MODE_FILTER && SECCOMP_RET_ERRNO" 142 " && BPF_JUMP && BPF_STMT") 143 144 #endif 145