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

Reply via email to