902636
From 58c4e9473b364fb62aac797b0d69fd8ddb02c8c7 Mon Sep 17 00:00:00 2001
902636
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
902636
Date: Mon, 27 Jan 2020 19:01:30 +0100
902636
Subject: [PATCH 059/116] virtiofsd: add seccomp whitelist
902636
MIME-Version: 1.0
902636
Content-Type: text/plain; charset=UTF-8
902636
Content-Transfer-Encoding: 8bit
902636
902636
RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
902636
Message-id: <20200127190227.40942-56-dgilbert@redhat.com>
902636
Patchwork-id: 93511
902636
O-Subject: [RHEL-AV-8.2 qemu-kvm PATCH 055/112] virtiofsd: add seccomp whitelist
902636
Bugzilla: 1694164
902636
RH-Acked-by: Philippe Mathieu-Daudé <philmd@redhat.com>
902636
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
902636
RH-Acked-by: Sergio Lopez Pascual <slp@redhat.com>
902636
902636
From: Stefan Hajnoczi <stefanha@redhat.com>
902636
902636
Only allow system calls that are needed by virtiofsd.  All other system
902636
calls cause SIGSYS to be directed at the thread and the process will
902636
coredump.
902636
902636
Restricting system calls reduces the kernel attack surface and limits
902636
what the process can do when compromised.
902636
902636
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
902636
with additional entries by:
902636
Signed-off-by: Ganesh Maharaj Mahalingam <ganesh.mahalingam@intel.com>
902636
Signed-off-by: Masayoshi Mizuma <m.mizuma@jp.fujitsu.com>
902636
Signed-off-by: Misono Tomohiro <misono.tomohiro@jp.fujitsu.com>
902636
Signed-off-by: piaojun <piaojun@huawei.com>
902636
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
902636
Signed-off-by: Eric Ren <renzhen@linux.alibaba.com>
902636
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
902636
(cherry picked from commit 4f8bde99c175ffd86b5125098a4707d43f5e80c6)
902636
902636
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
902636
---
902636
 Makefile                         |   5 +-
902636
 tools/virtiofsd/Makefile.objs    |   5 +-
902636
 tools/virtiofsd/passthrough_ll.c |   2 +
902636
 tools/virtiofsd/seccomp.c        | 151 +++++++++++++++++++++++++++++++++++++++
902636
 tools/virtiofsd/seccomp.h        |  14 ++++
902636
 5 files changed, 174 insertions(+), 3 deletions(-)
902636
 create mode 100644 tools/virtiofsd/seccomp.c
902636
 create mode 100644 tools/virtiofsd/seccomp.h
902636
902636
diff --git a/Makefile b/Makefile
902636
index 0e9755d..6879a06 100644
902636
--- a/Makefile
902636
+++ b/Makefile
902636
@@ -330,7 +330,7 @@ endif
902636
 endif
902636
 endif
902636
 
902636
-ifdef CONFIG_LINUX
902636
+ifeq ($(CONFIG_LINUX)$(CONFIG_SECCOMP),yy)
902636
 HELPERS-y += virtiofsd$(EXESUF)
902636
 vhost-user-json-y += tools/virtiofsd/50-qemu-virtiofsd.json
902636
 endif
902636
@@ -681,7 +681,8 @@ rdmacm-mux$(EXESUF): LIBS += "-libumad"
902636
 rdmacm-mux$(EXESUF): $(rdmacm-mux-obj-y) $(COMMON_LDADDS)
902636
 	$(call LINK, $^)
902636
 
902636
-ifdef CONFIG_LINUX # relies on Linux-specific syscalls
902636
+# relies on Linux-specific syscalls
902636
+ifeq ($(CONFIG_LINUX)$(CONFIG_SECCOMP),yy)
902636
 virtiofsd$(EXESUF): $(virtiofsd-obj-y) libvhost-user.a $(COMMON_LDADDS)
902636
 	$(call LINK, $^)
902636
 endif
902636
diff --git a/tools/virtiofsd/Makefile.objs b/tools/virtiofsd/Makefile.objs
902636
index 45a8075..076f667 100644
902636
--- a/tools/virtiofsd/Makefile.objs
902636
+++ b/tools/virtiofsd/Makefile.objs
902636
@@ -5,5 +5,8 @@ virtiofsd-obj-y = buffer.o \
902636
                   fuse_signals.o \
902636
                   fuse_virtio.o \
902636
                   helper.o \
902636
-                  passthrough_ll.o
902636
+                  passthrough_ll.o \
902636
+                  seccomp.o
902636
 
902636
+seccomp.o-cflags := $(SECCOMP_CFLAGS)
902636
+seccomp.o-libs := $(SECCOMP_LIBS)
902636
diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c
902636
index 0947d14..bd8925b 100644
902636
--- a/tools/virtiofsd/passthrough_ll.c
902636
+++ b/tools/virtiofsd/passthrough_ll.c
902636
@@ -59,6 +59,7 @@
902636
 #include <unistd.h>
902636
 
902636
 #include "passthrough_helpers.h"
902636
+#include "seccomp.h"
902636
 
902636
 struct lo_map_elem {
902636
     union {
902636
@@ -2091,6 +2092,7 @@ static void setup_sandbox(struct lo_data *lo, struct fuse_session *se)
902636
 {
902636
     setup_namespaces(lo, se);
902636
     setup_mounts(lo->source);
902636
+    setup_seccomp();
902636
 }
902636
 
902636
 int main(int argc, char *argv[])
902636
diff --git a/tools/virtiofsd/seccomp.c b/tools/virtiofsd/seccomp.c
902636
new file mode 100644
902636
index 0000000..691fb63
902636
--- /dev/null
902636
+++ b/tools/virtiofsd/seccomp.c
902636
@@ -0,0 +1,151 @@
902636
+/*
902636
+ * Seccomp sandboxing for virtiofsd
902636
+ *
902636
+ * Copyright (C) 2019 Red Hat, Inc.
902636
+ *
902636
+ * SPDX-License-Identifier: GPL-2.0-or-later
902636
+ */
902636
+
902636
+#include "qemu/osdep.h"
902636
+#include "seccomp.h"
902636
+#include "fuse_i.h"
902636
+#include "fuse_log.h"
902636
+#include <errno.h>
902636
+#include <glib.h>
902636
+#include <seccomp.h>
902636
+#include <stdlib.h>
902636
+
902636
+/* Bodge for libseccomp 2.4.2 which broke ppoll */
902636
+#if !defined(__SNR_ppoll) && defined(__SNR_brk)
902636
+#ifdef __NR_ppoll
902636
+#define __SNR_ppoll __NR_ppoll
902636
+#else
902636
+#define __SNR_ppoll __PNR_ppoll
902636
+#endif
902636
+#endif
902636
+
902636
+static const int syscall_whitelist[] = {
902636
+    /* TODO ireg sem*() syscalls */
902636
+    SCMP_SYS(brk),
902636
+    SCMP_SYS(capget), /* For CAP_FSETID */
902636
+    SCMP_SYS(capset),
902636
+    SCMP_SYS(clock_gettime),
902636
+    SCMP_SYS(clone),
902636
+#ifdef __NR_clone3
902636
+    SCMP_SYS(clone3),
902636
+#endif
902636
+    SCMP_SYS(close),
902636
+    SCMP_SYS(copy_file_range),
902636
+    SCMP_SYS(dup),
902636
+    SCMP_SYS(eventfd2),
902636
+    SCMP_SYS(exit),
902636
+    SCMP_SYS(exit_group),
902636
+    SCMP_SYS(fallocate),
902636
+    SCMP_SYS(fchmodat),
902636
+    SCMP_SYS(fchownat),
902636
+    SCMP_SYS(fcntl),
902636
+    SCMP_SYS(fdatasync),
902636
+    SCMP_SYS(fgetxattr),
902636
+    SCMP_SYS(flistxattr),
902636
+    SCMP_SYS(flock),
902636
+    SCMP_SYS(fremovexattr),
902636
+    SCMP_SYS(fsetxattr),
902636
+    SCMP_SYS(fstat),
902636
+    SCMP_SYS(fstatfs),
902636
+    SCMP_SYS(fsync),
902636
+    SCMP_SYS(ftruncate),
902636
+    SCMP_SYS(futex),
902636
+    SCMP_SYS(getdents),
902636
+    SCMP_SYS(getdents64),
902636
+    SCMP_SYS(getegid),
902636
+    SCMP_SYS(geteuid),
902636
+    SCMP_SYS(getpid),
902636
+    SCMP_SYS(gettid),
902636
+    SCMP_SYS(gettimeofday),
902636
+    SCMP_SYS(linkat),
902636
+    SCMP_SYS(lseek),
902636
+    SCMP_SYS(madvise),
902636
+    SCMP_SYS(mkdirat),
902636
+    SCMP_SYS(mknodat),
902636
+    SCMP_SYS(mmap),
902636
+    SCMP_SYS(mprotect),
902636
+    SCMP_SYS(mremap),
902636
+    SCMP_SYS(munmap),
902636
+    SCMP_SYS(newfstatat),
902636
+    SCMP_SYS(open),
902636
+    SCMP_SYS(openat),
902636
+    SCMP_SYS(ppoll),
902636
+    SCMP_SYS(prctl), /* TODO restrict to just PR_SET_NAME? */
902636
+    SCMP_SYS(preadv),
902636
+    SCMP_SYS(pread64),
902636
+    SCMP_SYS(pwritev),
902636
+    SCMP_SYS(pwrite64),
902636
+    SCMP_SYS(read),
902636
+    SCMP_SYS(readlinkat),
902636
+    SCMP_SYS(recvmsg),
902636
+    SCMP_SYS(renameat),
902636
+    SCMP_SYS(renameat2),
902636
+    SCMP_SYS(rt_sigaction),
902636
+    SCMP_SYS(rt_sigprocmask),
902636
+    SCMP_SYS(rt_sigreturn),
902636
+    SCMP_SYS(sendmsg),
902636
+    SCMP_SYS(setresgid),
902636
+    SCMP_SYS(setresuid),
902636
+#ifdef __NR_setresgid32
902636
+    SCMP_SYS(setresgid32),
902636
+#endif
902636
+#ifdef __NR_setresuid32
902636
+    SCMP_SYS(setresuid32),
902636
+#endif
902636
+    SCMP_SYS(set_robust_list),
902636
+    SCMP_SYS(symlinkat),
902636
+    SCMP_SYS(time), /* Rarely needed, except on static builds */
902636
+    SCMP_SYS(tgkill),
902636
+    SCMP_SYS(unlinkat),
902636
+    SCMP_SYS(utimensat),
902636
+    SCMP_SYS(write),
902636
+    SCMP_SYS(writev),
902636
+};
902636
+
902636
+void setup_seccomp(void)
902636
+{
902636
+    scmp_filter_ctx ctx;
902636
+    size_t i;
902636
+
902636
+#ifdef SCMP_ACT_KILL_PROCESS
902636
+    ctx = seccomp_init(SCMP_ACT_KILL_PROCESS);
902636
+    /* Handle a newer libseccomp but an older kernel */
902636
+    if (!ctx && errno == EOPNOTSUPP) {
902636
+        ctx = seccomp_init(SCMP_ACT_TRAP);
902636
+    }
902636
+#else
902636
+    ctx = seccomp_init(SCMP_ACT_TRAP);
902636
+#endif
902636
+    if (!ctx) {
902636
+        fuse_log(FUSE_LOG_ERR, "seccomp_init() failed\n");
902636
+        exit(1);
902636
+    }
902636
+
902636
+    for (i = 0; i < G_N_ELEMENTS(syscall_whitelist); i++) {
902636
+        if (seccomp_rule_add(ctx, SCMP_ACT_ALLOW,
902636
+                             syscall_whitelist[i], 0) != 0) {
902636
+            fuse_log(FUSE_LOG_ERR, "seccomp_rule_add syscall %d",
902636
+                     syscall_whitelist[i]);
902636
+            exit(1);
902636
+        }
902636
+    }
902636
+
902636
+    /* libvhost-user calls this for post-copy migration, we don't need it */
902636
+    if (seccomp_rule_add(ctx, SCMP_ACT_ERRNO(ENOSYS),
902636
+                         SCMP_SYS(userfaultfd), 0) != 0) {
902636
+        fuse_log(FUSE_LOG_ERR, "seccomp_rule_add userfaultfd failed\n");
902636
+        exit(1);
902636
+    }
902636
+
902636
+    if (seccomp_load(ctx) < 0) {
902636
+        fuse_log(FUSE_LOG_ERR, "seccomp_load() failed\n");
902636
+        exit(1);
902636
+    }
902636
+
902636
+    seccomp_release(ctx);
902636
+}
902636
diff --git a/tools/virtiofsd/seccomp.h b/tools/virtiofsd/seccomp.h
902636
new file mode 100644
902636
index 0000000..86bce72
902636
--- /dev/null
902636
+++ b/tools/virtiofsd/seccomp.h
902636
@@ -0,0 +1,14 @@
902636
+/*
902636
+ * Seccomp sandboxing for virtiofsd
902636
+ *
902636
+ * Copyright (C) 2019 Red Hat, Inc.
902636
+ *
902636
+ * SPDX-License-Identifier: GPL-2.0-or-later
902636
+ */
902636
+
902636
+#ifndef VIRTIOFSD_SECCOMP_H
902636
+#define VIRTIOFSD_SECCOMP_H
902636
+
902636
+void setup_seccomp(void);
902636
+
902636
+#endif /* VIRTIOFSD_SECCOMP_H */
902636
-- 
902636
1.8.3.1
902636