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