qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

passthrough_seccomp.c (4522B)


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