qemu/tools/virtiofsd/passthrough_seccomp.c
<<
>>
Prefs
   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}
 178