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