158d83921SDag-Erling Smørgrav /* 258d83921SDag-Erling Smørgrav * Copyright (c) 2012 Will Drewry <wad@dataspill.org> 358d83921SDag-Erling Smørgrav * 458d83921SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 558d83921SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 658d83921SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 758d83921SDag-Erling Smørgrav * 858d83921SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 958d83921SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1058d83921SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1158d83921SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1258d83921SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1358d83921SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1458d83921SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1558d83921SDag-Erling Smørgrav */ 1658d83921SDag-Erling Smørgrav 1758d83921SDag-Erling Smørgrav /* 1858d83921SDag-Erling Smørgrav * Uncomment the SANDBOX_SECCOMP_FILTER_DEBUG macro below to help diagnose 1958d83921SDag-Erling Smørgrav * filter breakage during development. *Do not* use this in production, 2058d83921SDag-Erling Smørgrav * as it relies on making library calls that are unsafe in signal context. 2158d83921SDag-Erling Smørgrav * 2258d83921SDag-Erling Smørgrav * Instead, live systems the auditctl(8) may be used to monitor failures. 2358d83921SDag-Erling Smørgrav * E.g. 2458d83921SDag-Erling Smørgrav * auditctl -a task,always -F uid=<privsep uid> 2558d83921SDag-Erling Smørgrav */ 26*f374ba41SEd Maste /* #define SANDBOX_SECCOMP_FILTER_DEBUG 1 */ 2758d83921SDag-Erling Smørgrav 2838a52bd3SEd Maste #if 0 2938a52bd3SEd Maste /* 3038a52bd3SEd Maste * For older toolchains, it may be necessary to use the kernel 3138a52bd3SEd Maste * headers directly. 3238a52bd3SEd Maste */ 3358d83921SDag-Erling Smørgrav #ifdef SANDBOX_SECCOMP_FILTER_DEBUG 3458d83921SDag-Erling Smørgrav # include <asm/siginfo.h> 3558d83921SDag-Erling Smørgrav # define __have_siginfo_t 1 3658d83921SDag-Erling Smørgrav # define __have_sigval_t 1 3758d83921SDag-Erling Smørgrav # define __have_sigevent_t 1 3858d83921SDag-Erling Smørgrav #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ 3938a52bd3SEd Maste #endif 4058d83921SDag-Erling Smørgrav 4158d83921SDag-Erling Smørgrav #include "includes.h" 4258d83921SDag-Erling Smørgrav 4358d83921SDag-Erling Smørgrav #ifdef SANDBOX_SECCOMP_FILTER 4458d83921SDag-Erling Smørgrav 4558d83921SDag-Erling Smørgrav #include <sys/types.h> 4658d83921SDag-Erling Smørgrav #include <sys/resource.h> 4758d83921SDag-Erling Smørgrav #include <sys/prctl.h> 4819261079SEd Maste #include <sys/mman.h> 4919261079SEd Maste #include <sys/syscall.h> 5058d83921SDag-Erling Smørgrav 51557f75e5SDag-Erling Smørgrav #include <linux/net.h> 5258d83921SDag-Erling Smørgrav #include <linux/audit.h> 5358d83921SDag-Erling Smørgrav #include <linux/filter.h> 5458d83921SDag-Erling Smørgrav #include <linux/seccomp.h> 5558d83921SDag-Erling Smørgrav #include <elf.h> 5658d83921SDag-Erling Smørgrav 5758d83921SDag-Erling Smørgrav #include <asm/unistd.h> 584f52dfbbSDag-Erling Smørgrav #ifdef __s390__ 594f52dfbbSDag-Erling Smørgrav #include <asm/zcrypt.h> 604f52dfbbSDag-Erling Smørgrav #endif 6158d83921SDag-Erling Smørgrav 6258d83921SDag-Erling Smørgrav #include <errno.h> 6358d83921SDag-Erling Smørgrav #include <signal.h> 6458d83921SDag-Erling Smørgrav #include <stdarg.h> 6558d83921SDag-Erling Smørgrav #include <stddef.h> /* for offsetof */ 6658d83921SDag-Erling Smørgrav #include <stdio.h> 6758d83921SDag-Erling Smørgrav #include <stdlib.h> 6858d83921SDag-Erling Smørgrav #include <string.h> 6958d83921SDag-Erling Smørgrav #include <unistd.h> 7058d83921SDag-Erling Smørgrav 7158d83921SDag-Erling Smørgrav #include "log.h" 7258d83921SDag-Erling Smørgrav #include "ssh-sandbox.h" 7358d83921SDag-Erling Smørgrav #include "xmalloc.h" 7458d83921SDag-Erling Smørgrav 7558d83921SDag-Erling Smørgrav /* Linux seccomp_filter sandbox */ 7658d83921SDag-Erling Smørgrav #define SECCOMP_FILTER_FAIL SECCOMP_RET_KILL 7758d83921SDag-Erling Smørgrav 7858d83921SDag-Erling Smørgrav /* Use a signal handler to emit violations when debugging */ 7958d83921SDag-Erling Smørgrav #ifdef SANDBOX_SECCOMP_FILTER_DEBUG 8058d83921SDag-Erling Smørgrav # undef SECCOMP_FILTER_FAIL 8158d83921SDag-Erling Smørgrav # define SECCOMP_FILTER_FAIL SECCOMP_RET_TRAP 8258d83921SDag-Erling Smørgrav #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ 8358d83921SDag-Erling Smørgrav 84d93a896eSDag-Erling Smørgrav #if __BYTE_ORDER == __LITTLE_ENDIAN 85d93a896eSDag-Erling Smørgrav # define ARG_LO_OFFSET 0 86d93a896eSDag-Erling Smørgrav # define ARG_HI_OFFSET sizeof(uint32_t) 87d93a896eSDag-Erling Smørgrav #elif __BYTE_ORDER == __BIG_ENDIAN 88d93a896eSDag-Erling Smørgrav # define ARG_LO_OFFSET sizeof(uint32_t) 89d93a896eSDag-Erling Smørgrav # define ARG_HI_OFFSET 0 90d93a896eSDag-Erling Smørgrav #else 91d93a896eSDag-Erling Smørgrav #error "Unknown endianness" 92d93a896eSDag-Erling Smørgrav #endif 93d93a896eSDag-Erling Smørgrav 9458d83921SDag-Erling Smørgrav /* Simple helpers to avoid manual errors (but larger BPF programs). */ 9558d83921SDag-Erling Smørgrav #define SC_DENY(_nr, _errno) \ 96d93a896eSDag-Erling Smørgrav BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 1), \ 9758d83921SDag-Erling Smørgrav BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno)) 9858d83921SDag-Erling Smørgrav #define SC_ALLOW(_nr) \ 99d93a896eSDag-Erling Smørgrav BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 1), \ 10058d83921SDag-Erling Smørgrav BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) 101557f75e5SDag-Erling Smørgrav #define SC_ALLOW_ARG(_nr, _arg_nr, _arg_val) \ 102d93a896eSDag-Erling Smørgrav BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 6), \ 10319261079SEd Maste /* load and test syscall argument, low word */ \ 104557f75e5SDag-Erling Smørgrav BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 105d93a896eSDag-Erling Smørgrav offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_LO_OFFSET), \ 106d93a896eSDag-Erling Smørgrav BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \ 107d93a896eSDag-Erling Smørgrav ((_arg_val) & 0xFFFFFFFF), 0, 3), \ 10819261079SEd Maste /* load and test syscall argument, high word */ \ 109d93a896eSDag-Erling Smørgrav BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 110d93a896eSDag-Erling Smørgrav offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_HI_OFFSET), \ 111d93a896eSDag-Erling Smørgrav BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, \ 112d93a896eSDag-Erling Smørgrav (((uint32_t)((uint64_t)(_arg_val) >> 32)) & 0xFFFFFFFF), 0, 1), \ 113557f75e5SDag-Erling Smørgrav BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \ 114557f75e5SDag-Erling Smørgrav /* reload syscall number; all rules expect it in accumulator */ \ 115557f75e5SDag-Erling Smørgrav BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 116557f75e5SDag-Erling Smørgrav offsetof(struct seccomp_data, nr)) 11719261079SEd Maste /* Allow if syscall argument contains only values in mask */ 11819261079SEd Maste #define SC_ALLOW_ARG_MASK(_nr, _arg_nr, _arg_mask) \ 11919261079SEd Maste BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, (_nr), 0, 8), \ 12019261079SEd Maste /* load, mask and test syscall argument, low word */ \ 12119261079SEd Maste BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 12219261079SEd Maste offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_LO_OFFSET), \ 12319261079SEd Maste BPF_STMT(BPF_ALU+BPF_AND+BPF_K, ~((_arg_mask) & 0xFFFFFFFF)), \ 12419261079SEd Maste BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 4), \ 12519261079SEd Maste /* load, mask and test syscall argument, high word */ \ 12619261079SEd Maste BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 12719261079SEd Maste offsetof(struct seccomp_data, args[(_arg_nr)]) + ARG_HI_OFFSET), \ 12819261079SEd Maste BPF_STMT(BPF_ALU+BPF_AND+BPF_K, \ 12919261079SEd Maste ~(((uint32_t)((uint64_t)(_arg_mask) >> 32)) & 0xFFFFFFFF)), \ 13019261079SEd Maste BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 1), \ 13119261079SEd Maste BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW), \ 13219261079SEd Maste /* reload syscall number; all rules expect it in accumulator */ \ 13319261079SEd Maste BPF_STMT(BPF_LD+BPF_W+BPF_ABS, \ 13419261079SEd Maste offsetof(struct seccomp_data, nr)) 13558d83921SDag-Erling Smørgrav 13658d83921SDag-Erling Smørgrav /* Syscall filtering set for preauth. */ 13758d83921SDag-Erling Smørgrav static const struct sock_filter preauth_insns[] = { 13858d83921SDag-Erling Smørgrav /* Ensure the syscall arch convention is as expected. */ 13958d83921SDag-Erling Smørgrav BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 14058d83921SDag-Erling Smørgrav offsetof(struct seccomp_data, arch)), 14158d83921SDag-Erling Smørgrav BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_AUDIT_ARCH, 1, 0), 14258d83921SDag-Erling Smørgrav BPF_STMT(BPF_RET+BPF_K, SECCOMP_FILTER_FAIL), 14358d83921SDag-Erling Smørgrav /* Load the syscall number for checking. */ 14458d83921SDag-Erling Smørgrav BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 14558d83921SDag-Erling Smørgrav offsetof(struct seccomp_data, nr)), 146557f75e5SDag-Erling Smørgrav 147557f75e5SDag-Erling Smørgrav /* Syscalls to non-fatally deny */ 148076ad2f8SDag-Erling Smørgrav #ifdef __NR_lstat 149d93a896eSDag-Erling Smørgrav SC_DENY(__NR_lstat, EACCES), 150076ad2f8SDag-Erling Smørgrav #endif 151076ad2f8SDag-Erling Smørgrav #ifdef __NR_lstat64 152d93a896eSDag-Erling Smørgrav SC_DENY(__NR_lstat64, EACCES), 153076ad2f8SDag-Erling Smørgrav #endif 154557f75e5SDag-Erling Smørgrav #ifdef __NR_fstat 155d93a896eSDag-Erling Smørgrav SC_DENY(__NR_fstat, EACCES), 156557f75e5SDag-Erling Smørgrav #endif 157557f75e5SDag-Erling Smørgrav #ifdef __NR_fstat64 158d93a896eSDag-Erling Smørgrav SC_DENY(__NR_fstat64, EACCES), 159557f75e5SDag-Erling Smørgrav #endif 16019261079SEd Maste #ifdef __NR_fstatat64 16119261079SEd Maste SC_DENY(__NR_fstatat64, EACCES), 16219261079SEd Maste #endif 163557f75e5SDag-Erling Smørgrav #ifdef __NR_open 164d93a896eSDag-Erling Smørgrav SC_DENY(__NR_open, EACCES), 165557f75e5SDag-Erling Smørgrav #endif 166557f75e5SDag-Erling Smørgrav #ifdef __NR_openat 167d93a896eSDag-Erling Smørgrav SC_DENY(__NR_openat, EACCES), 168557f75e5SDag-Erling Smørgrav #endif 169557f75e5SDag-Erling Smørgrav #ifdef __NR_newfstatat 170d93a896eSDag-Erling Smørgrav SC_DENY(__NR_newfstatat, EACCES), 171557f75e5SDag-Erling Smørgrav #endif 172557f75e5SDag-Erling Smørgrav #ifdef __NR_stat 173d93a896eSDag-Erling Smørgrav SC_DENY(__NR_stat, EACCES), 17458d83921SDag-Erling Smørgrav #endif 175557f75e5SDag-Erling Smørgrav #ifdef __NR_stat64 176d93a896eSDag-Erling Smørgrav SC_DENY(__NR_stat64, EACCES), 177b83788ffSDag-Erling Smørgrav #endif 17819261079SEd Maste #ifdef __NR_shmget 17919261079SEd Maste SC_DENY(__NR_shmget, EACCES), 18019261079SEd Maste #endif 18119261079SEd Maste #ifdef __NR_shmat 18219261079SEd Maste SC_DENY(__NR_shmat, EACCES), 18319261079SEd Maste #endif 18419261079SEd Maste #ifdef __NR_shmdt 18519261079SEd Maste SC_DENY(__NR_shmdt, EACCES), 18619261079SEd Maste #endif 18719261079SEd Maste #ifdef __NR_ipc 18819261079SEd Maste SC_DENY(__NR_ipc, EACCES), 18919261079SEd Maste #endif 19019261079SEd Maste #ifdef __NR_statx 19119261079SEd Maste SC_DENY(__NR_statx, EACCES), 19219261079SEd Maste #endif 193557f75e5SDag-Erling Smørgrav 194557f75e5SDag-Erling Smørgrav /* Syscalls to permit */ 195557f75e5SDag-Erling Smørgrav #ifdef __NR_brk 196d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_brk), 19758d83921SDag-Erling Smørgrav #endif 198557f75e5SDag-Erling Smørgrav #ifdef __NR_clock_gettime 199d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_clock_gettime), 200557f75e5SDag-Erling Smørgrav #endif 20119261079SEd Maste #ifdef __NR_clock_gettime64 20219261079SEd Maste SC_ALLOW(__NR_clock_gettime64), 20319261079SEd Maste #endif 204557f75e5SDag-Erling Smørgrav #ifdef __NR_close 205d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_close), 206557f75e5SDag-Erling Smørgrav #endif 207557f75e5SDag-Erling Smørgrav #ifdef __NR_exit 208d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_exit), 209557f75e5SDag-Erling Smørgrav #endif 210557f75e5SDag-Erling Smørgrav #ifdef __NR_exit_group 211d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_exit_group), 212557f75e5SDag-Erling Smørgrav #endif 2132f513db7SEd Maste #ifdef __NR_futex 2142f513db7SEd Maste SC_ALLOW(__NR_futex), 2152f513db7SEd Maste #endif 21619261079SEd Maste #ifdef __NR_futex_time64 21719261079SEd Maste SC_ALLOW(__NR_futex_time64), 21819261079SEd Maste #endif 219190cef3dSDag-Erling Smørgrav #ifdef __NR_geteuid 220190cef3dSDag-Erling Smørgrav SC_ALLOW(__NR_geteuid), 221190cef3dSDag-Erling Smørgrav #endif 222190cef3dSDag-Erling Smørgrav #ifdef __NR_geteuid32 223190cef3dSDag-Erling Smørgrav SC_ALLOW(__NR_geteuid32), 224190cef3dSDag-Erling Smørgrav #endif 225557f75e5SDag-Erling Smørgrav #ifdef __NR_getpgid 226d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_getpgid), 227557f75e5SDag-Erling Smørgrav #endif 228557f75e5SDag-Erling Smørgrav #ifdef __NR_getpid 229d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_getpid), 230557f75e5SDag-Erling Smørgrav #endif 231acc1a9efSDag-Erling Smørgrav #ifdef __NR_getrandom 232d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_getrandom), 233acc1a9efSDag-Erling Smørgrav #endif 2341323ec57SEd Maste #ifdef __NR_gettid 2351323ec57SEd Maste SC_ALLOW(__NR_gettid), 2361323ec57SEd Maste #endif 237557f75e5SDag-Erling Smørgrav #ifdef __NR_gettimeofday 238d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_gettimeofday), 239557f75e5SDag-Erling Smørgrav #endif 240190cef3dSDag-Erling Smørgrav #ifdef __NR_getuid 241190cef3dSDag-Erling Smørgrav SC_ALLOW(__NR_getuid), 242190cef3dSDag-Erling Smørgrav #endif 243190cef3dSDag-Erling Smørgrav #ifdef __NR_getuid32 244190cef3dSDag-Erling Smørgrav SC_ALLOW(__NR_getuid32), 245190cef3dSDag-Erling Smørgrav #endif 246557f75e5SDag-Erling Smørgrav #ifdef __NR_madvise 247d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_madvise), 24858d83921SDag-Erling Smørgrav #endif 24958d83921SDag-Erling Smørgrav #ifdef __NR_mmap 25019261079SEd Maste SC_ALLOW_ARG_MASK(__NR_mmap, 2, PROT_READ|PROT_WRITE|PROT_NONE), 25158d83921SDag-Erling Smørgrav #endif 252557f75e5SDag-Erling Smørgrav #ifdef __NR_mmap2 25319261079SEd Maste SC_ALLOW_ARG_MASK(__NR_mmap2, 2, PROT_READ|PROT_WRITE|PROT_NONE), 25419261079SEd Maste #endif 25519261079SEd Maste #ifdef __NR_mprotect 25619261079SEd Maste SC_ALLOW_ARG_MASK(__NR_mprotect, 2, PROT_READ|PROT_WRITE|PROT_NONE), 257a0ee8cc6SDag-Erling Smørgrav #endif 258557f75e5SDag-Erling Smørgrav #ifdef __NR_mremap 259d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_mremap), 260557f75e5SDag-Erling Smørgrav #endif 261557f75e5SDag-Erling Smørgrav #ifdef __NR_munmap 262d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_munmap), 263557f75e5SDag-Erling Smørgrav #endif 264190cef3dSDag-Erling Smørgrav #ifdef __NR_nanosleep 265190cef3dSDag-Erling Smørgrav SC_ALLOW(__NR_nanosleep), 266190cef3dSDag-Erling Smørgrav #endif 26719261079SEd Maste #ifdef __NR_clock_nanosleep 26819261079SEd Maste SC_ALLOW(__NR_clock_nanosleep), 26919261079SEd Maste #endif 27019261079SEd Maste #ifdef __NR_clock_nanosleep_time64 27119261079SEd Maste SC_ALLOW(__NR_clock_nanosleep_time64), 27219261079SEd Maste #endif 27319261079SEd Maste #ifdef __NR_clock_gettime64 27419261079SEd Maste SC_ALLOW(__NR_clock_gettime64), 27519261079SEd Maste #endif 276557f75e5SDag-Erling Smørgrav #ifdef __NR__newselect 277d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR__newselect), 278557f75e5SDag-Erling Smørgrav #endif 2791323ec57SEd Maste #ifdef __NR_ppoll 2801323ec57SEd Maste SC_ALLOW(__NR_ppoll), 2811323ec57SEd Maste #endif 28258def461SEd Maste #ifdef __NR_ppoll_time64 28358def461SEd Maste SC_ALLOW(__NR_ppoll_time64), 28458def461SEd Maste #endif 285557f75e5SDag-Erling Smørgrav #ifdef __NR_poll 286d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_poll), 287557f75e5SDag-Erling Smørgrav #endif 288557f75e5SDag-Erling Smørgrav #ifdef __NR_pselect6 289d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_pselect6), 290557f75e5SDag-Erling Smørgrav #endif 29119261079SEd Maste #ifdef __NR_pselect6_time64 29219261079SEd Maste SC_ALLOW(__NR_pselect6_time64), 29319261079SEd Maste #endif 294557f75e5SDag-Erling Smørgrav #ifdef __NR_read 295d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_read), 296557f75e5SDag-Erling Smørgrav #endif 29758d83921SDag-Erling Smørgrav #ifdef __NR_rt_sigprocmask 298d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_rt_sigprocmask), 299557f75e5SDag-Erling Smørgrav #endif 300557f75e5SDag-Erling Smørgrav #ifdef __NR_select 301d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_select), 302557f75e5SDag-Erling Smørgrav #endif 303557f75e5SDag-Erling Smørgrav #ifdef __NR_shutdown 304d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_shutdown), 305557f75e5SDag-Erling Smørgrav #endif 306557f75e5SDag-Erling Smørgrav #ifdef __NR_sigprocmask 307d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_sigprocmask), 30858d83921SDag-Erling Smørgrav #endif 309557f75e5SDag-Erling Smørgrav #ifdef __NR_time 310d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_time), 311557f75e5SDag-Erling Smørgrav #endif 312557f75e5SDag-Erling Smørgrav #ifdef __NR_write 313d93a896eSDag-Erling Smørgrav SC_ALLOW(__NR_write), 314557f75e5SDag-Erling Smørgrav #endif 315*f374ba41SEd Maste #ifdef __NR_writev 316*f374ba41SEd Maste SC_ALLOW(__NR_writev), 317*f374ba41SEd Maste #endif 318557f75e5SDag-Erling Smørgrav #ifdef __NR_socketcall 319d93a896eSDag-Erling Smørgrav SC_ALLOW_ARG(__NR_socketcall, 0, SYS_SHUTDOWN), 3204f52dfbbSDag-Erling Smørgrav SC_DENY(__NR_socketcall, EACCES), 321d93a896eSDag-Erling Smørgrav #endif 322d93a896eSDag-Erling Smørgrav #if defined(__NR_ioctl) && defined(__s390__) 323d93a896eSDag-Erling Smørgrav /* Allow ioctls for ICA crypto card on s390 */ 324d93a896eSDag-Erling Smørgrav SC_ALLOW_ARG(__NR_ioctl, 1, Z90STAT_STATUS_MASK), 325d93a896eSDag-Erling Smørgrav SC_ALLOW_ARG(__NR_ioctl, 1, ICARSAMODEXPO), 326d93a896eSDag-Erling Smørgrav SC_ALLOW_ARG(__NR_ioctl, 1, ICARSACRT), 32719261079SEd Maste SC_ALLOW_ARG(__NR_ioctl, 1, ZSECSENDCPRB), 32819261079SEd Maste /* Allow ioctls for EP11 crypto card on s390 */ 32919261079SEd Maste SC_ALLOW_ARG(__NR_ioctl, 1, ZSENDEP11CPRB), 330d93a896eSDag-Erling Smørgrav #endif 331d93a896eSDag-Erling Smørgrav #if defined(__x86_64__) && defined(__ILP32__) && defined(__X32_SYSCALL_BIT) 332d93a896eSDag-Erling Smørgrav /* 333d93a896eSDag-Erling Smørgrav * On Linux x32, the clock_gettime VDSO falls back to the 334d93a896eSDag-Erling Smørgrav * x86-64 syscall under some circumstances, e.g. 335d93a896eSDag-Erling Smørgrav * https://bugs.debian.org/849923 336d93a896eSDag-Erling Smørgrav */ 3374f52dfbbSDag-Erling Smørgrav SC_ALLOW(__NR_clock_gettime & ~__X32_SYSCALL_BIT), 338557f75e5SDag-Erling Smørgrav #endif 339557f75e5SDag-Erling Smørgrav 340557f75e5SDag-Erling Smørgrav /* Default deny */ 34158d83921SDag-Erling Smørgrav BPF_STMT(BPF_RET+BPF_K, SECCOMP_FILTER_FAIL), 34258d83921SDag-Erling Smørgrav }; 34358d83921SDag-Erling Smørgrav 34458d83921SDag-Erling Smørgrav static const struct sock_fprog preauth_program = { 34558d83921SDag-Erling Smørgrav .len = (unsigned short)(sizeof(preauth_insns)/sizeof(preauth_insns[0])), 34658d83921SDag-Erling Smørgrav .filter = (struct sock_filter *)preauth_insns, 34758d83921SDag-Erling Smørgrav }; 34858d83921SDag-Erling Smørgrav 34958d83921SDag-Erling Smørgrav struct ssh_sandbox { 35058d83921SDag-Erling Smørgrav pid_t child_pid; 35158d83921SDag-Erling Smørgrav }; 35258d83921SDag-Erling Smørgrav 35358d83921SDag-Erling Smørgrav struct ssh_sandbox * 354f7167e0eSDag-Erling Smørgrav ssh_sandbox_init(struct monitor *monitor) 35558d83921SDag-Erling Smørgrav { 35658d83921SDag-Erling Smørgrav struct ssh_sandbox *box; 35758d83921SDag-Erling Smørgrav 35858d83921SDag-Erling Smørgrav /* 35958d83921SDag-Erling Smørgrav * Strictly, we don't need to maintain any state here but we need 36058d83921SDag-Erling Smørgrav * to return non-NULL to satisfy the API. 36158d83921SDag-Erling Smørgrav */ 36258d83921SDag-Erling Smørgrav debug3("%s: preparing seccomp filter sandbox", __func__); 36358d83921SDag-Erling Smørgrav box = xcalloc(1, sizeof(*box)); 36458d83921SDag-Erling Smørgrav box->child_pid = 0; 36558d83921SDag-Erling Smørgrav 36658d83921SDag-Erling Smørgrav return box; 36758d83921SDag-Erling Smørgrav } 36858d83921SDag-Erling Smørgrav 36958d83921SDag-Erling Smørgrav #ifdef SANDBOX_SECCOMP_FILTER_DEBUG 37058d83921SDag-Erling Smørgrav extern struct monitor *pmonitor; 37138a52bd3SEd Maste void mm_log_handler(LogLevel level, int forced, const char *msg, void *ctx); 37258d83921SDag-Erling Smørgrav 37358d83921SDag-Erling Smørgrav static void 37458d83921SDag-Erling Smørgrav ssh_sandbox_violation(int signum, siginfo_t *info, void *void_context) 37558d83921SDag-Erling Smørgrav { 37658d83921SDag-Erling Smørgrav char msg[256]; 37758d83921SDag-Erling Smørgrav 37858d83921SDag-Erling Smørgrav snprintf(msg, sizeof(msg), 37958d83921SDag-Erling Smørgrav "%s: unexpected system call (arch:0x%x,syscall:%d @ %p)", 38058d83921SDag-Erling Smørgrav __func__, info->si_arch, info->si_syscall, info->si_call_addr); 38138a52bd3SEd Maste mm_log_handler(SYSLOG_LEVEL_FATAL, 0, msg, pmonitor); 38258d83921SDag-Erling Smørgrav _exit(1); 38358d83921SDag-Erling Smørgrav } 38458d83921SDag-Erling Smørgrav 38558d83921SDag-Erling Smørgrav static void 38658d83921SDag-Erling Smørgrav ssh_sandbox_child_debugging(void) 38758d83921SDag-Erling Smørgrav { 38858d83921SDag-Erling Smørgrav struct sigaction act; 38958d83921SDag-Erling Smørgrav sigset_t mask; 39058d83921SDag-Erling Smørgrav 39158d83921SDag-Erling Smørgrav debug3("%s: installing SIGSYS handler", __func__); 39258d83921SDag-Erling Smørgrav memset(&act, 0, sizeof(act)); 39358d83921SDag-Erling Smørgrav sigemptyset(&mask); 39458d83921SDag-Erling Smørgrav sigaddset(&mask, SIGSYS); 39558d83921SDag-Erling Smørgrav 39658d83921SDag-Erling Smørgrav act.sa_sigaction = &ssh_sandbox_violation; 39758d83921SDag-Erling Smørgrav act.sa_flags = SA_SIGINFO; 39858d83921SDag-Erling Smørgrav if (sigaction(SIGSYS, &act, NULL) == -1) 39958d83921SDag-Erling Smørgrav fatal("%s: sigaction(SIGSYS): %s", __func__, strerror(errno)); 40058d83921SDag-Erling Smørgrav if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) 40158d83921SDag-Erling Smørgrav fatal("%s: sigprocmask(SIGSYS): %s", 40258d83921SDag-Erling Smørgrav __func__, strerror(errno)); 40358d83921SDag-Erling Smørgrav } 40458d83921SDag-Erling Smørgrav #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ 40558d83921SDag-Erling Smørgrav 40658d83921SDag-Erling Smørgrav void 40758d83921SDag-Erling Smørgrav ssh_sandbox_child(struct ssh_sandbox *box) 40858d83921SDag-Erling Smørgrav { 4091323ec57SEd Maste struct rlimit rl_zero, rl_one = {.rlim_cur = 1, .rlim_max = 1}; 41058d83921SDag-Erling Smørgrav int nnp_failed = 0; 41158d83921SDag-Erling Smørgrav 41258d83921SDag-Erling Smørgrav /* Set rlimits for completeness if possible. */ 41358d83921SDag-Erling Smørgrav rl_zero.rlim_cur = rl_zero.rlim_max = 0; 41458d83921SDag-Erling Smørgrav if (setrlimit(RLIMIT_FSIZE, &rl_zero) == -1) 41558d83921SDag-Erling Smørgrav fatal("%s: setrlimit(RLIMIT_FSIZE, { 0, 0 }): %s", 41658d83921SDag-Erling Smørgrav __func__, strerror(errno)); 4171323ec57SEd Maste /* 4181323ec57SEd Maste * Cannot use zero for nfds, because poll(2) will fail with 4191323ec57SEd Maste * errno=EINVAL if npfds>RLIMIT_NOFILE. 4201323ec57SEd Maste */ 4211323ec57SEd Maste if (setrlimit(RLIMIT_NOFILE, &rl_one) == -1) 42258d83921SDag-Erling Smørgrav fatal("%s: setrlimit(RLIMIT_NOFILE, { 0, 0 }): %s", 42358d83921SDag-Erling Smørgrav __func__, strerror(errno)); 42458d83921SDag-Erling Smørgrav if (setrlimit(RLIMIT_NPROC, &rl_zero) == -1) 42558d83921SDag-Erling Smørgrav fatal("%s: setrlimit(RLIMIT_NPROC, { 0, 0 }): %s", 42658d83921SDag-Erling Smørgrav __func__, strerror(errno)); 42758d83921SDag-Erling Smørgrav 42858d83921SDag-Erling Smørgrav #ifdef SANDBOX_SECCOMP_FILTER_DEBUG 42958d83921SDag-Erling Smørgrav ssh_sandbox_child_debugging(); 43058d83921SDag-Erling Smørgrav #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ 43158d83921SDag-Erling Smørgrav 43258d83921SDag-Erling Smørgrav debug3("%s: setting PR_SET_NO_NEW_PRIVS", __func__); 43358d83921SDag-Erling Smørgrav if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) { 43458d83921SDag-Erling Smørgrav debug("%s: prctl(PR_SET_NO_NEW_PRIVS): %s", 43558d83921SDag-Erling Smørgrav __func__, strerror(errno)); 43658d83921SDag-Erling Smørgrav nnp_failed = 1; 43758d83921SDag-Erling Smørgrav } 43858d83921SDag-Erling Smørgrav debug3("%s: attaching seccomp filter program", __func__); 43958d83921SDag-Erling Smørgrav if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &preauth_program) == -1) 44058d83921SDag-Erling Smørgrav debug("%s: prctl(PR_SET_SECCOMP): %s", 44158d83921SDag-Erling Smørgrav __func__, strerror(errno)); 44258d83921SDag-Erling Smørgrav else if (nnp_failed) 44358d83921SDag-Erling Smørgrav fatal("%s: SECCOMP_MODE_FILTER activated but " 44458d83921SDag-Erling Smørgrav "PR_SET_NO_NEW_PRIVS failed", __func__); 44558d83921SDag-Erling Smørgrav } 44658d83921SDag-Erling Smørgrav 44758d83921SDag-Erling Smørgrav void 44858d83921SDag-Erling Smørgrav ssh_sandbox_parent_finish(struct ssh_sandbox *box) 44958d83921SDag-Erling Smørgrav { 45058d83921SDag-Erling Smørgrav free(box); 45158d83921SDag-Erling Smørgrav debug3("%s: finished", __func__); 45258d83921SDag-Erling Smørgrav } 45358d83921SDag-Erling Smørgrav 45458d83921SDag-Erling Smørgrav void 45558d83921SDag-Erling Smørgrav ssh_sandbox_parent_preauth(struct ssh_sandbox *box, pid_t child_pid) 45658d83921SDag-Erling Smørgrav { 45758d83921SDag-Erling Smørgrav box->child_pid = child_pid; 45858d83921SDag-Erling Smørgrav } 45958d83921SDag-Erling Smørgrav 46058d83921SDag-Erling Smørgrav #endif /* SANDBOX_SECCOMP_FILTER */ 461