[Libreoffice-commits] online.git: 4 commits - common/Log.cpp common/Log.hpp common/Seccomp.cpp common/SigUtil.cpp common/SigUtil.hpp
Michael Meeks
michael.meeks at collabora.com
Fri Apr 28 18:11:07 UTC 2017
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.meeks at 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.meeks at 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.meeks at 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.meeks at 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
More information about the Libreoffice-commits
mailing list