Commit 0abb63a7 authored by jan.koester's avatar jan.koester
Browse files

test

parent 8cbf51cb
Loading
Loading
Loading
Loading
+42 −0
Changes for src/runtime.cpp: 42 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <cerrno>
#include <csignal>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstring>
@@ -42,8 +43,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <net/if.h>
#include <poll.h>
#include <grp.h>
#include <linux/audit.h>
#include <linux/capability.h>
#include <linux/ethtool.h>
#include <linux/filter.h>
#include <linux/seccomp.h>
#include <linux/sockios.h>
#include <sched.h>
#include <sys/mount.h>
@@ -337,6 +341,44 @@ struct Pid1 {
        for (int c = 0; c <= lastCap(); ++c)
            if (!keep.count(c) && prctl(PR_CAPBSET_DROP, c, 0, 0, 0) != 0 && errno != EINVAL)
                fail(sysErr("PR_CAPBSET_DROP", errno));
        if (!keep.count(capabilityNumber("SYSLOG"))) noKernelLog();
    }

    // the kernel log isn't namespaced, and the kernel lets CAP_SYS_ADMIN (a
    // booted OS keeps it) read it as well as CAP_SYSLOG: syslog(2) gives
    // EPERM unless Capability=SYSLOG -- as in Docker's seccomp profile;
    // /dev/kmsg, the other way, isn't in the container's /dev
    void noKernelLog() {
#if defined(__x86_64__)
        const uint32_t arch = AUDIT_ARCH_X86_64;
#elif defined(__aarch64__)
        const uint32_t arch = AUDIT_ARCH_AARCH64;
#elif defined(__i386__)
        const uint32_t arch = AUDIT_ARCH_I386;
#else
        return;
#endif
        std::vector<sock_filter> f = {
            BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(seccomp_data, arch)),
#if defined(__x86_64__)
            // i386 programs: their syslog is 103 too
            BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, AUDIT_ARCH_I386, 1, 0),
#endif
            BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, arch, 0, 3),
            BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(seccomp_data, nr)),
#if defined(__x86_64__)
            BPF_STMT(BPF_ALU | BPF_AND | BPF_K, ~0x40000000u),  // x32
#endif
            BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_syslog, 0, 1),
            BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | EPERM),
            BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
        };
#if defined(__x86_64__)
        f[2].jf = 4;  // past the x32 mask too
#endif
        sock_fprog prog{(unsigned short)f.size(), f.data()};
        // still root with every capability here: no PR_SET_NO_NEW_PRIVS needed
        if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0) != 0) fail(sysErr("seccomp", errno));
    }

    // ---- the command ----
+3 −0
Changes for src/settings.h: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -40,6 +40,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *   Environment=KEY=value        (one per line)
 *   User=www-data                WorkingDirectory=/srv
 *   Hostname=web                 Capability=NET_ADMIN   DropCapability=NET_RAW
 *                                (Capability=SYSLOG also lets dmesg read
 *                                the host's kernel log; without it, syslog(2)
 *                                gives EPERM even with SYS_ADMIN)
 *
 *   [Files]
 *   ReadOnly=no                  Bind=/srv/www:/usr/share/nginx/html