[Libreoffice-commits] online.git: common/Seccomp.cpp common/Seccomp.hpp configure.ac kit/Kit.cpp Makefile.am
Michael Meeks
michael.meeks at collabora.com
Fri Apr 28 13:26:55 UTC 2017
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.meeks at 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.");
More information about the Libreoffice-commits
mailing list