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#ifdef __NR_rseq
  95    SCMP_SYS(rseq), /* required since glibc 2.35 */
  96#endif
  97    SCMP_SYS(rt_sigaction),
  98    SCMP_SYS(rt_sigprocmask),
  99    SCMP_SYS(rt_sigreturn),
 100    SCMP_SYS(sched_getattr),
 101    SCMP_SYS(sched_setattr),
 102    SCMP_SYS(sendmsg),
 103    SCMP_SYS(setresgid),
 104    SCMP_SYS(setresuid),
 105#ifdef __NR_setresgid32
 106    SCMP_SYS(setresgid32),
 107#endif
 108#ifdef __NR_setresuid32
 109    SCMP_SYS(setresuid32),
 110#endif
 111    SCMP_SYS(set_robust_list),
 112    SCMP_SYS(setxattr),
 113    SCMP_SYS(symlinkat),
 114    SCMP_SYS(syncfs),
 115    SCMP_SYS(time), /* Rarely needed, except on static builds */
 116    SCMP_SYS(tgkill),
 117    SCMP_SYS(unlinkat),
 118    SCMP_SYS(unshare),
 119    SCMP_SYS(utimensat),
 120    SCMP_SYS(write),
 121    SCMP_SYS(writev),
 122    SCMP_SYS(umask),
 123};
 124
 125/* Syscalls used when --syslog is enabled */
 126static const int syscall_allowlist_syslog[] = {
 127    SCMP_SYS(send),
 128    SCMP_SYS(sendto),
 129};
 130
 131static void add_allowlist(scmp_filter_ctx ctx, const int syscalls[], size_t len)
 132{
 133    size_t i;
 134
 135    for (i = 0; i < len; i++) {
 136        if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW, syscalls[i], 0) != 0) {
 137            fuse_log(FUSE_LOG_ERR, "seccomp_rule_add syscall %d failed\n",
 138                     syscalls[i]);
 139            exit(1);
 140        }
 141    }
 142}
 143
 144void setup_seccomp(bool enable_syslog)
 145{
 146    scmp_filter_ctx ctx;
 147
 148#ifdef SCMP_ACT_KILL_PROCESS
 149    ctx = seccomp_init(SCMP_ACT_KILL_PROCESS);
 150    /* Handle a newer libseccomp but an older kernel */
 151    if (!ctx && errno == EOPNOTSUPP) {
 152        ctx = seccomp_init(SCMP_ACT_TRAP);
 153    }
 154#else
 155    ctx = seccomp_init(SCMP_ACT_TRAP);
 156#endif
 157    if (!ctx) {
 158        fuse_log(FUSE_LOG_ERR, "seccomp_init() failed\n");
 159        exit(1);
 160    }
 161
 162    add_allowlist(ctx, syscall_allowlist, G_N_ELEMENTS(syscall_allowlist));
 163    if (enable_syslog) {
 164        add_allowlist(ctx, syscall_allowlist_syslog,
 165                      G_N_ELEMENTS(syscall_allowlist_syslog));
 166    }
 167
 168    /* libvhost-user calls this for post-copy migration, we don't need it */
 169    if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOSYS),
 170                         SCMP_SYS(userfaultfd), 0) != 0) {
 171        fuse_log(FUSE_LOG_ERR, "seccomp_rule_add userfaultfd failed\n");
 172        exit(1);
 173    }
 174
 175    if (seccomp_load(ctx) < 0) {
 176        fuse_log(FUSE_LOG_ERR, "seccomp_load() failed\n");
 177        exit(1);
 178    }
 179
 180    seccomp_release(ctx);
 181}
 182