Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfb8800e authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Enable seccomp in init with generated policy"

parents 1e7cdf3c db929bf9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ LOCAL_SRC_FILES:= \
    init.cpp \
    keychords.cpp \
    property_service.cpp \
    seccomp.cpp \
    signal_handler.cpp \
    ueventd.cpp \
    ueventd_parser.cpp \
@@ -96,6 +97,7 @@ LOCAL_STATIC_LIBRARIES := \
    libbase \
    libc \
    libselinux \
    libseccomp_policy \
    liblog \
    libcrypto_utils \
    libcrypto \
+7 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@
#include "keychords.h"
#include "log.h"
#include "property_service.h"
#include "seccomp.h"
#include "service.h"
#include "signal_handler.h"
#include "ueventd.h"
@@ -763,6 +764,12 @@ int main(int argc, char** argv) {

        // Now set up SELinux for second stage.
        selinux_initialize(false);

        // Install system-wide seccomp filter
        if (!set_seccomp_filter()) {
            LOG(ERROR) << "Failed to set seccomp policy";
            security_failure();
        }
    }

    // These directories were necessarily created before initial policy load

init/seccomp.cpp

0 → 100644
+213 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "seccomp.h"

#include <vector>

#include <sys/prctl.h>

#include <linux/unistd.h>
#include <linux/audit.h>
#include <linux/filter.h>
#include <linux/seccomp.h>

#include "log.h"
#include "seccomp_policy.h"

#define syscall_nr (offsetof(struct seccomp_data, nr))
#define arch_nr (offsetof(struct seccomp_data, arch))

#if   defined __arm__
#define AUDIT_ARCH_NR AUDIT_ARCH_ARM
#elif defined __aarch64__
#define AUDIT_ARCH_NR AUDIT_ARCH_AARCH64
#define AUDIT_ARCH_NR32 AUDIT_ARCH_ARM
#elif defined __i386__
#define AUDIT_ARCH_NR AUDIT_ARCH_I386
#elif defined __x86_64__
#define AUDIT_ARCH_NR AUDIT_ARCH_X86_64
#define AUDIT_ARCH_NR32 AUDIT_ARCH_I386
#elif defined __mips64__
#define AUDIT_ARCH_NR AUDIT_ARCH_MIPS64
#define AUDIT_ARCH_NR32 AUDIT_ARCH_MIPS
#elif defined __mips__ && !defined __mips64__
#define AUDIT_ARCH_NR AUDIT_ARCH_MIPS
#else
#error "Could not determine AUDIT_ARCH_NR for this architecture"
#endif

typedef std::vector<sock_filter> filter;

// We want to keep the below inline functions for debugging and future
// development even though they are not used currently.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-function"

static inline void Kill(filter& f) {
    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL));
}

static inline void Trap(filter& f) {
    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP));
}

static inline void Error(filter& f, __u16 retcode) {
    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO + retcode));
}

inline static void Trace(filter& f) {
    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE));
}

inline static void Allow(filter& f) {
    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW));
}

inline static void AllowSyscall(filter& f, __u32 num) {
    f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, num, 0, 1));
    f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW));
}

inline static void ExamineSyscall(filter& f) {
    f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_nr));
}

#ifdef AUDIT_ARCH_NR32
inline static int SetValidateArchitectureJumpTarget(size_t offset, filter& f) {
    auto jump_length = f.size() - offset - 1;
    auto u8_jump_length = (__u8) jump_length;
    if (u8_jump_length != jump_length) {
        LOG(ERROR) << "Can't set jump greater than 255 - actual jump is " << jump_length;
        return -1;
    }
    f[offset] = BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_NR32, u8_jump_length, 0);
    return 0;
}
#endif

inline static size_t ValidateArchitectureAndJumpIfNeeded(filter& f) {
    f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, arch_nr));

#ifdef AUDIT_ARCH_NR32
    f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_NR, 2, 0));
    f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_NR32, 1, 0));
    Kill(f);
    return f.size() - 2;
#else
    f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, AUDIT_ARCH_NR, 1, 0));
    Kill(f);
    return 0;
#endif
}

#pragma clang diagnostic pop

static bool install_filter(filter const& f) {
    struct sock_fprog prog = {
        (unsigned short) f.size(),
        (struct sock_filter*) &f[0],
    };

    if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) {
        PLOG(ERROR) << "SECCOMP: Could not set seccomp filter";
        return false;
    }

    LOG(INFO) << "SECCOMP: Global filter installed";
    return true;
}

bool set_seccomp_filter() {
    filter f;

    // Note that for mixed 64/32 bit architectures, ValidateArchitecture inserts a
    // jump that must be changed to point to the start of the 32-bit policy
    // 32 bit syscalls will not hit the policy between here and the call to SetJump
#ifdef AUDIT_ARCH_NR32
    auto offset_to_32bit_filter =
#endif
        ValidateArchitectureAndJumpIfNeeded(f);

    // Native filter
    ExamineSyscall(f);

#ifdef __aarch64__
    // Syscalls needed to boot Android
    AllowSyscall(f, __NR_pivot_root);
    AllowSyscall(f, __NR_ioprio_get);
    AllowSyscall(f, __NR_ioprio_set);
    AllowSyscall(f, __NR_gettid);
    AllowSyscall(f, __NR_futex);
    AllowSyscall(f, __NR_clone);
    AllowSyscall(f, __NR_rt_sigreturn);
    AllowSyscall(f, __NR_rt_tgsigqueueinfo);
    AllowSyscall(f, __NR_add_key);
    AllowSyscall(f, __NR_request_key);
    AllowSyscall(f, __NR_keyctl);
    AllowSyscall(f, __NR_restart_syscall);
    AllowSyscall(f, __NR_getrandom);

    // Needed for performance tools
    AllowSyscall(f, __NR_perf_event_open);

    // Needed for treble
    AllowSyscall(f, __NR_finit_module);

    // Needed for trusty
    AllowSyscall(f, __NR_syncfs);

     // arm64-only filter - autogenerated from bionic syscall usage
    for (size_t i = 0; i < arm64_filter_size; ++i)
        f.push_back(arm64_filter[i]);
#else
    // Generic policy
    Allow(f);
#endif

#ifdef AUDIT_ARCH_NR32
    if (SetValidateArchitectureJumpTarget(offset_to_32bit_filter, f) != 0)
        return -1;

    // 32-bit filter for 64-bit platforms
    ExamineSyscall(f);

#ifdef __aarch64__
    // Syscalls needed to boot android
    AllowSyscall(f, 120); // __NR_clone
    AllowSyscall(f, 240); // __NR_futex
    AllowSyscall(f, 119); // __NR_sigreturn
    AllowSyscall(f, 173); // __NR_rt_sigreturn
    AllowSyscall(f, 363); // __NR_rt_tgsigqueueinfo
    AllowSyscall(f, 224); // __NR_gettid

    // Syscalls needed to run Chrome
    AllowSyscall(f, 383); // __NR_seccomp - needed to start Chrome
    AllowSyscall(f, 384); // __NR_getrandom - needed to start Chrome

    // Syscalls needed to run GFXBenchmark
    AllowSyscall(f, 190); // __NR_vfork

    // arm32-on-arm64 only filter - autogenerated from bionic syscall usage
    for (size_t i = 0; i < arm_filter_size; ++i)
        f.push_back(arm_filter[i]);
#else
    // Generic policy
    Allow(f);
#endif
#endif
    return install_filter(f);
}

init/seccomp.h

0 → 100644
+22 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef SECCOMP_H
#define SECCOMP_H

bool set_seccomp_filter();

#endif