common/Log.cpp | 15 ++++++++ common/Log.hpp | 2 + common/Seccomp.cpp | 95 ++++++++++++++++++++++++++++++++++++++++++++--------- common/SigUtil.cpp | 11 ++++-- common/SigUtil.hpp | 3 + 5 files changed, 108 insertions(+), 18 deletions(-)
New commits: commit 31818b7dd65dcacf0c52fa8900ae129bc91c72b3 Author: Michael Meeks <michael.me...@collabora.com> Date: Fri Apr 28 19:06:20 2017 +0100 Trap rather than kill from seccomp and log invalid syscalls. Change-Id: I319c10776476fea865dd7a95921f1b08b689e09f diff --git a/common/Seccomp.cpp b/common/Seccomp.cpp index 3156f199..b0709cd6 100644 --- a/common/Seccomp.cpp +++ b/common/Seccomp.cpp @@ -19,22 +19,59 @@ #include <sys/capability.h> #include <unistd.h> #include <utime.h> - -#include <common/Log.hpp> - -#include <Seccomp.hpp> - +#include <signal.h> #include <sys/prctl.h> #include <linux/audit.h> #include <linux/filter.h> #include <linux/seccomp.h> +#include <common/Log.hpp> +#include <common/SigUtil.hpp> +#include <Seccomp.hpp> + +#ifndef SYS_SECCOMP +# define SYS_SECCOMP 1 +#endif + #if defined(__x86_64__) # define AUDIT_ARCH_NR AUDIT_ARCH_X86_64 +# define REG_SYSCALL REG_RAX #else # error "Platform does not support seccomp filtering yet - unsafe." #endif +extern "C" { + +static void handleSysSignal(int /* signal */, + siginfo_t *info, + void *context) +{ + ucontext_t *uctx = reinterpret_cast<ucontext_t *>(context); + + Log::signalLogPrefix(); + Log::signalLog("SIGSYS trapped with code: "); + Log::signalLogNumber(info->si_code); + Log::signalLog(" and context "); + Log::signalLogNumber(reinterpret_cast<size_t>(context)); + Log::signalLog("\n"); + + if (info->si_code != SYS_SECCOMP || !uctx) + return; + + unsigned int syscall = uctx->uc_mcontext.gregs[REG_SYSCALL]; + + Log::signalLogPrefix(); + Log::signalLog(" seccomp trapped signal, un-authorized sys-call: "); + Log::signalLogNumber(syscall); + Log::signalLog("\n"); + + SigUtil::dumpBacktrace(); + + _exit(1); +} + +} // extern "C" + namespace Seccomp { bool lockdown(Type type) @@ -47,7 +84,7 @@ bool lockdown(Type type) #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) + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_TRAP) struct sock_filter filterCode[] = { // Check our architecture is correct. @@ -139,8 +176,7 @@ bool lockdown(Type type) 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. + // allow the rest. BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) }; @@ -160,7 +196,17 @@ bool lockdown(Type type) return false; } + // Trap, log, and exit on failure + struct sigaction action; + + sigemptyset(&action.sa_mask); + action.sa_flags = SA_SIGINFO; + action.sa_handler = reinterpret_cast<__sighandler_t>(handleSysSignal); + + sigaction(SIGSYS, &action, nullptr); + LOG_TRC("Install seccomp filter successfully."); + return true; } commit 08c70f1315ac49a253f76b4ea08cba4a9ac7a9b6 Author: Michael Meeks <michael.me...@collabora.com> Date: Fri Apr 28 19:05:45 2017 +0100 Signal safe number logging (lame but useful). Change-Id: I0b6095fc08dcc237a224b5942ab5a09e6820e43f diff --git a/common/Log.cpp b/common/Log.cpp index 71b5a5b6..e4a9e995 100644 --- a/common/Log.cpp +++ b/common/Log.cpp @@ -78,6 +78,21 @@ namespace Log } } + // We need a signal safe means of writing messages + // $ man 7 signal + void signalLogNumber(size_t num) + { + int i; + char buf[22]; + buf[21] = '\0'; + for (i = 20; i > 0 && num > 0; --i) + { + buf[i] = '0' + num % 10; + num /= 10; + } + signalLog(buf + i + 1); + } + char* prefix(char* buffer, const char* level, bool sigSafe) { long osTid; diff --git a/common/Log.hpp b/common/Log.hpp index 3f64303a..21de30f6 100644 --- a/common/Log.hpp +++ b/common/Log.hpp @@ -50,6 +50,8 @@ namespace Log void signalLogPrefix(); /// Signal safe logging void signalLog(const char* message); + /// Signal log number + void signalLogNumber(size_t num); /// The following is to write streaming logs. /// Log::info() << "Value: 0x" << std::hex << value commit a7eeacf9e05ed2447cfb6881e7bf3fcdfc25ccf4 Author: Michael Meeks <michael.me...@collabora.com> Date: Fri Apr 28 18:08:57 2017 +0100 SigUtil: split out dumpBacktrace. Change-Id: I33121de341051bf40ae0d42d1d6d44843d6d1e97 diff --git a/common/SigUtil.cpp b/common/SigUtil.cpp index c6c4ffe4..48899f37 100644 --- a/common/SigUtil.cpp +++ b/common/SigUtil.cpp @@ -190,6 +190,14 @@ namespace SigUtil sigaction(signal, &action, nullptr); + dumpBacktrace(); + + // let default handler process the signal + kill(Poco::Process::id(), signal); + } + + void dumpBacktrace() + { char header[32]; sprintf(header, "Backtrace %d:\n", getpid()); @@ -224,9 +232,6 @@ namespace SigUtil LOG_ERR("Sleeping 30s to allow debugging."); sleep(30); } - - // let default handler process the signal - kill(Poco::Process::id(), signal); } void setFatalSignals() diff --git a/common/SigUtil.hpp b/common/SigUtil.hpp index 2b69578a..7cc8f6d7 100644 --- a/common/SigUtil.hpp +++ b/common/SigUtil.hpp @@ -56,6 +56,9 @@ namespace SigUtil /// after a certain (short) timeout. bool killChild(const int pid); + /// Dump a signal-safe back-trace + void dumpBacktrace(); + } // end namespace SigUtil #endif commit bc31103a5d55c78bb8626da2cb280a88420fc05b Author: Michael Meeks <michael.me...@collabora.com> Date: Fri Apr 28 16:46:10 2017 +0100 Seccomp: filter more syscalls. Change-Id: I2cc203d48e4592c5f182e675383e96a13b87bc36 diff --git a/common/Seccomp.cpp b/common/Seccomp.cpp index d2959fd4..3156f199 100644 --- a/common/Seccomp.cpp +++ b/common/Seccomp.cpp @@ -41,7 +41,10 @@ bool lockdown(Type type) { (void)type; // so far just the kit. - // FIXME: partition better to give log() branching. + #define ACCEPT_SYSCALL(name) \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) + #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) @@ -55,8 +58,23 @@ bool lockdown(Type type) // 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 ? + // ------------------------------------------------------------ + // --- First white-list the syscalls we frequently use. --- + // ------------------------------------------------------------ + ACCEPT_SYSCALL(recvfrom), + ACCEPT_SYSCALL(write), + ACCEPT_SYSCALL(futex), + + // glibc's 'poll' has to answer for this lot: + ACCEPT_SYSCALL(epoll_wait), + ACCEPT_SYSCALL(epoll_ctl), + ACCEPT_SYSCALL(epoll_create), + ACCEPT_SYSCALL(close), + ACCEPT_SYSCALL(nanosleep), + + // ------------------------------------------------------------ + // --- Now block everything that we don't like the look of. --- + // ------------------------------------------------------------ // FIXME: should we bother blocking calls that have early // permission checks we don't meet ? @@ -73,17 +91,16 @@ bool lockdown(Type type) KILL_SYSCALL(setitimer), KILL_SYSCALL(sendfile), KILL_SYSCALL(shutdown), - KILL_SYSCALL(listen), + KILL_SYSCALL(listen), // server sockets + KILL_SYSCALL(accept), // server sockets #if 0 KILL_SYSCALL(wait4), #endif KILL_SYSCALL(kill), // ! KILL_SYSCALL(shmctl), - KILL_SYSCALL(ptrace), // ! + KILL_SYSCALL(ptrace), // tracing KILL_SYSCALL(capset), -#if 0 KILL_SYSCALL(uselib), -#endif KILL_SYSCALL(personality), // ! KILL_SYSCALL(vhangup), KILL_SYSCALL(modify_ldt), // ! @@ -114,7 +131,9 @@ bool lockdown(Type type) KILL_SYSCALL(tee), KILL_SYSCALL(vmsplice), // vm bits KILL_SYSCALL(move_pages), // vm bits + KILL_SYSCALL(accept4), // server sockets KILL_SYSCALL(inotify_init1), + KILL_SYSCALL(perf_event_open), // profiling KILL_SYSCALL(fanotify_init), KILL_SYSCALL(fanotify_mark), KILL_SYSCALL(seccomp), // no further fiddling _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits