Makefile.am        |    2 
 common/Seccomp.cpp |  150 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 common/Seccomp.hpp |   21 +++++++
 configure.ac       |    3 +
 kit/Kit.cpp        |    8 ++
 5 files changed, 184 insertions(+)

New commits:
commit 7f4f7526674af84660b50b8156e7c3c741d0751c
Author: Michael Meeks <michael.me...@collabora.com>
Date:   Fri Apr 28 11:02:06 2017 +0100

    Initial seccomp work.
    
    Add a list of unhelpful looking system calls to improve containment.
    
    Change-Id: I2e4bf3e0a6a752d427299728663d17120586bb10

diff --git a/Makefile.am b/Makefile.am
index cfcfd7c3..622fe550 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -47,6 +47,7 @@ shared_sources = common/FileUtil.cpp \
                  common/Log.cpp \
                  common/Protocol.cpp \
                  common/Session.cpp \
+                 common/Seccomp.cpp \
                  common/MessageQueue.cpp \
                  common/SigUtil.cpp \
                  common/SpookyV2.cpp \
@@ -152,6 +153,7 @@ shared_headers = common/Common.hpp \
                  common/Log.hpp \
                  common/LOOLWebSocket.hpp \
                  common/Protocol.hpp \
+                 common/Seccomp.hpp \
                  common/Session.hpp \
                  common/Unit.hpp \
                  common/UnitHTTP.hpp \
diff --git a/common/Seccomp.cpp b/common/Seccomp.cpp
new file mode 100644
index 00000000..d2959fd4
--- /dev/null
+++ b/common/Seccomp.cpp
@@ -0,0 +1,150 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; 
fill-column: 100 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+/*
+ * Code to lock-down the environment of the processes we run, to avoid
+ * exotic or un-necessary system calls to be used to break containment.
+ */
+
+#include "config.h"
+
+#include <dlfcn.h>
+#include <ftw.h>
+#include <malloc.h>
+#include <sys/capability.h>
+#include <unistd.h>
+#include <utime.h>
+
+#include <common/Log.hpp>
+
+#include <Seccomp.hpp>
+
+#include <sys/prctl.h>
+#include <linux/audit.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+
+#if defined(__x86_64__)
+#  define AUDIT_ARCH_NR AUDIT_ARCH_X86_64
+#else
+#  error "Platform does not support seccomp filtering yet - unsafe."
+#endif
+
+namespace Seccomp {
+
+bool lockdown(Type type)
+{
+    (void)type; // so far just the kit.
+
+    // FIXME: partition better to give log() branching.
+    #define KILL_SYSCALL(name) \
+        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \
+        BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
+
+    struct sock_filter filterCode[] = {
+        // Check our architecture is correct.
+        BPF_STMT(BPF_LD+BPF_W+BPF_ABS,  offsetof(struct seccomp_data, arch)),
+        BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, AUDIT_ARCH_NR, 1, 0),
+        BPF_STMT(BPF_RET+BPF_K,         SECCOMP_RET_KILL),
+
+        // Load sycall number
+        BPF_STMT(BPF_LD+BPF_W+BPF_ABS,  offsetof(struct seccomp_data, nr)),
+
+        // FIXME: white-list low-numbers / safe common-cases first
+        // at the expense of some cross-platform complexity ?
+
+        // FIXME: should we bother blocking calls that have early
+        // permission checks we don't meet ?
+
+#if 0
+        // cf. eg. /usr/include/asm/unistd_64.h ...
+        KILL_SYSCALL(ioctl),
+        KILL_SYSCALL(mincore),
+        KILL_SYSCALL(shmget),
+        KILL_SYSCALL(shmat),
+        KILL_SYSCALL(shmctl),
+#endif
+        KILL_SYSCALL(getitimer),
+        KILL_SYSCALL(setitimer),
+        KILL_SYSCALL(sendfile),
+        KILL_SYSCALL(shutdown),
+        KILL_SYSCALL(listen),
+#if 0
+        KILL_SYSCALL(wait4),
+#endif
+        KILL_SYSCALL(kill),   // !
+        KILL_SYSCALL(shmctl),
+        KILL_SYSCALL(ptrace), // !
+        KILL_SYSCALL(capset),
+#if 0
+        KILL_SYSCALL(uselib),
+#endif
+        KILL_SYSCALL(personality), // !
+        KILL_SYSCALL(vhangup),
+        KILL_SYSCALL(modify_ldt), // !
+        KILL_SYSCALL(pivot_root), // !
+        KILL_SYSCALL(chroot),
+        KILL_SYSCALL(acct),   // !
+        KILL_SYSCALL(sync),   // I/O perf.
+        KILL_SYSCALL(mount),
+        KILL_SYSCALL(umount2),
+        KILL_SYSCALL(swapon),
+        KILL_SYSCALL(swapoff),
+        KILL_SYSCALL(reboot), // !
+        KILL_SYSCALL(sethostname),
+        KILL_SYSCALL(setdomainname),
+        KILL_SYSCALL(tkill),
+        KILL_SYSCALL(mbind), // vm bits
+        KILL_SYSCALL(set_mempolicy), // vm bits
+        KILL_SYSCALL(get_mempolicy), // vm bits
+        KILL_SYSCALL(kexec_load),
+        KILL_SYSCALL(add_key),     // kernel keyring
+        KILL_SYSCALL(request_key), // kernel keyring
+        KILL_SYSCALL(keyctl),      // kernel keyring
+        KILL_SYSCALL(inotify_init),
+        KILL_SYSCALL(inotify_add_watch),
+        KILL_SYSCALL(inotify_rm_watch),
+        KILL_SYSCALL(unshare),
+        KILL_SYSCALL(splice),
+        KILL_SYSCALL(tee),
+        KILL_SYSCALL(vmsplice), // vm bits
+        KILL_SYSCALL(move_pages), // vm bits
+        KILL_SYSCALL(inotify_init1),
+        KILL_SYSCALL(fanotify_init),
+        KILL_SYSCALL(fanotify_mark),
+        KILL_SYSCALL(seccomp), // no further fiddling
+        KILL_SYSCALL(bpf),     // no further fiddling
+
+        // allow the rest - FIXME: prolly we should white-list
+        // but LibreOffice is rather large.
+        BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
+    };
+
+    struct sock_fprog filter = {
+        sizeof(filterCode)/sizeof(filterCode[0]), // length
+        filterCode
+    };
+
+    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
+    {
+        LOG_ERR("Cannot turn off acquisition of new privileges for us & 
children");
+        return false;
+    }
+    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &filter))
+    {
+        LOG_ERR("Failed to install seccomp syscall filter");
+        return false;
+    }
+
+    LOG_TRC("Install seccomp filter successfully.");
+    return true;
+}
+
+} // namespace Seccomp
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/common/Seccomp.hpp b/common/Seccomp.hpp
new file mode 100644
index 00000000..865b5c91
--- /dev/null
+++ b/common/Seccomp.hpp
@@ -0,0 +1,21 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+#ifndef INCLUDED_SECCOMP_HPP
+#define INCLUDED_SECCOMP_HPP
+
+namespace Seccomp {
+    enum Type { KIT, WSD };
+
+    /// Lock-down a process hard - @returns true on success.
+    bool lockdown(Type type);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/configure.ac b/configure.ac
index 3f5daff2..391f23ea 100644
--- a/configure.ac
+++ b/configure.ac
@@ -267,6 +267,9 @@ AC_CHECK_HEADERS([LibreOfficeKit/LibreOfficeKit.h],
 AC_CHECK_HEADERS([Poco/Net/WebSocket.h],
                  [],
                  [AC_MSG_ERROR([header Poco/Net/WebSocket.h not found, perhaps 
you want to use --with-poco-includes])])
+AC_CHECK_HEADERS([linux/seccomp.h],
+                 [],
+                 [AC_MSG_ERROR([critical security header linux/seccomp.h not 
found.])])
 
 AC_MSG_CHECKING([POCO version])
 AC_COMPILE_IFELSE([AC_LANG_SOURCE([
diff --git a/kit/Kit.cpp b/kit/Kit.cpp
index 121f20e8..144c3b2c 100644
--- a/kit/Kit.cpp
+++ b/kit/Kit.cpp
@@ -65,6 +65,7 @@
 #include "Util.hpp"
 
 #include "common/SigUtil.hpp"
+#include "common/Seccomp.hpp"
 
 #ifdef FUZZER
 #include <kit/DummyLibreOfficeKit.hpp>
@@ -1761,6 +1762,13 @@ void lokit_main(const std::string& childRoot,
             }
         }
 
+        // Lock down the syscalls that can be used
+        if (!Seccomp::lockdown(Seccomp::Type::KIT))
+        {
+            LOG_ERR("LibreOfficeKit security lockdown failed. Exiting.");
+            std::_Exit(Application::EXIT_SOFTWARE);
+        }
+
         assert(loKit);
         LOG_INF("Process is ready.");
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to