passthrough_seccomp.c (4399B)
1/* 2 * Seccomp sandboxing for virtiofsd 3 * 4 * Copyright (C) 2019 Red Hat, Inc. 5 * 6 * SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9#include "qemu/osdep.h" 10#include "passthrough_seccomp.h" 11#include "fuse_i.h" 12#include "fuse_log.h" 13#include <seccomp.h> 14 15/* Bodge for libseccomp 2.4.2 which broke ppoll */ 16#if !defined(__SNR_ppoll) && defined(__SNR_brk) 17#ifdef __NR_ppoll 18#define __SNR_ppoll __NR_ppoll 19#else 20#define __SNR_ppoll __PNR_ppoll 21#endif 22#endif 23 24static const int syscall_allowlist[] = { 25 /* TODO ireg sem*() syscalls */ 26 SCMP_SYS(brk), 27 SCMP_SYS(capget), /* For CAP_FSETID */ 28 SCMP_SYS(capset), 29 SCMP_SYS(clock_gettime), 30 SCMP_SYS(clone), 31#ifdef __NR_clone3 32 SCMP_SYS(clone3), 33#endif 34 SCMP_SYS(close), 35 SCMP_SYS(copy_file_range), 36 SCMP_SYS(dup), 37 SCMP_SYS(eventfd2), 38 SCMP_SYS(exit), 39 SCMP_SYS(exit_group), 40 SCMP_SYS(fallocate), 41 SCMP_SYS(fchdir), 42 SCMP_SYS(fchmod), 43 SCMP_SYS(fchmodat), 44 SCMP_SYS(fchownat), 45 SCMP_SYS(fcntl), 46 SCMP_SYS(fdatasync), 47 SCMP_SYS(fgetxattr), 48 SCMP_SYS(flistxattr), 49 SCMP_SYS(flock), 50 SCMP_SYS(fremovexattr), 51 SCMP_SYS(fsetxattr), 52 SCMP_SYS(fstat), 53 SCMP_SYS(fstatfs), 54 SCMP_SYS(fstatfs64), 55 SCMP_SYS(fsync), 56 SCMP_SYS(ftruncate), 57 SCMP_SYS(futex), 58 SCMP_SYS(getdents), 59 SCMP_SYS(getdents64), 60 SCMP_SYS(getegid), 61 SCMP_SYS(geteuid), 62 SCMP_SYS(getpid), 63 SCMP_SYS(gettid), 64 SCMP_SYS(gettimeofday), 65 SCMP_SYS(getxattr), 66 SCMP_SYS(linkat), 67 SCMP_SYS(listxattr), 68 SCMP_SYS(lseek), 69 SCMP_SYS(_llseek), /* For POWER */ 70 SCMP_SYS(madvise), 71 SCMP_SYS(mkdirat), 72 SCMP_SYS(mknodat), 73 SCMP_SYS(mmap), 74 SCMP_SYS(mprotect), 75 SCMP_SYS(mremap), 76 SCMP_SYS(munmap), 77 SCMP_SYS(newfstatat), 78 SCMP_SYS(statx), 79 SCMP_SYS(open), 80 SCMP_SYS(openat), 81 SCMP_SYS(ppoll), 82 SCMP_SYS(prctl), /* TODO restrict to just PR_SET_NAME? */ 83 SCMP_SYS(preadv), 84 SCMP_SYS(pread64), 85 SCMP_SYS(pwritev), 86 SCMP_SYS(pwrite64), 87 SCMP_SYS(read), 88 SCMP_SYS(readlinkat), 89 SCMP_SYS(recvmsg), 90 SCMP_SYS(renameat), 91 SCMP_SYS(renameat2), 92 SCMP_SYS(removexattr), 93 SCMP_SYS(restart_syscall), 94 SCMP_SYS(rt_sigaction), 95 SCMP_SYS(rt_sigprocmask), 96 SCMP_SYS(rt_sigreturn), 97 SCMP_SYS(sched_getattr), 98 SCMP_SYS(sched_setattr), 99 SCMP_SYS(sendmsg), 100 SCMP_SYS(setresgid), 101 SCMP_SYS(setresuid), 102#ifdef __NR_setresgid32 103 SCMP_SYS(setresgid32), 104#endif 105#ifdef __NR_setresuid32 106 SCMP_SYS(setresuid32), 107#endif 108 SCMP_SYS(set_robust_list), 109 SCMP_SYS(setxattr), 110 SCMP_SYS(symlinkat), 111 SCMP_SYS(time), /* Rarely needed, except on static builds */ 112 SCMP_SYS(tgkill), 113 SCMP_SYS(unlinkat), 114 SCMP_SYS(unshare), 115 SCMP_SYS(utimensat), 116 SCMP_SYS(write), 117 SCMP_SYS(writev), 118 SCMP_SYS(umask), 119}; 120 121/* Syscalls used when --syslog is enabled */ 122static const int syscall_allowlist_syslog[] = { 123 SCMP_SYS(send), 124 SCMP_SYS(sendto), 125}; 126 127static void add_allowlist(scmp_filter_ctx ctx, const int syscalls[], size_t len) 128{ 129 size_t i; 130 131 for (i = 0; i < len; i++) { 132 if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls[i], 0) != 0) { 133 fuse_log(FUSE_LOG_ERR, "seccomp_rule_add syscall %d failed\n", 134 syscalls[i]); 135 exit(1); 136 } 137 } 138} 139 140void setup_seccomp(bool enable_syslog) 141{ 142 scmp_filter_ctx ctx; 143 144#ifdef SCMP_ACT_KILL_PROCESS 145 ctx = seccomp_init(SCMP_ACT_KILL_PROCESS); 146 /* Handle a newer libseccomp but an older kernel */ 147 if (!ctx && errno == EOPNOTSUPP) { 148 ctx = seccomp_init(SCMP_ACT_TRAP); 149 } 150#else 151 ctx = seccomp_init(SCMP_ACT_TRAP); 152#endif 153 if (!ctx) { 154 fuse_log(FUSE_LOG_ERR, "seccomp_init() failed\n"); 155 exit(1); 156 } 157 158 add_allowlist(ctx, syscall_allowlist, G_N_ELEMENTS(syscall_allowlist)); 159 if (enable_syslog) { 160 add_allowlist(ctx, syscall_allowlist_syslog, 161 G_N_ELEMENTS(syscall_allowlist_syslog)); 162 } 163 164 /* libvhost-user calls this for post-copy migration, we don't need it */ 165 if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOSYS), 166 SCMP_SYS(userfaultfd), 0) != 0) { 167 fuse_log(FUSE_LOG_ERR, "seccomp_rule_add userfaultfd failed\n"); 168 exit(1); 169 } 170 171 if (seccomp_load(ctx) < 0) { 172 fuse_log(FUSE_LOG_ERR, "seccomp_load() failed\n"); 173 exit(1); 174 } 175 176 seccomp_release(ctx); 177}