| /* |
| * seccomp.c - seccomp utility functions |
| * Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "config.h" |
| |
| #include <asm/unistd.h> |
| #include <elf.h> |
| #include <errno.h> |
| #include <sys/prctl.h> |
| #include <stddef.h> |
| #include <stdint.h> |
| #include <stdlib.h> |
| #include <sys/syscall.h> |
| #include <unistd.h> |
| |
| #include <linux/audit.h> |
| #include <linux/filter.h> |
| |
| #include "src/seccomp.h" |
| |
| /* Linux seccomp_filter sandbox */ |
| #define SECCOMP_FILTER_FAIL SECCOMP_RET_KILL |
| |
| /* Use a signal handler to emit violations when debugging */ |
| #ifdef SECCOMP_FILTER_DEBUG |
| # undef SECCOMP_FILTER_FAIL |
| # define SECCOMP_FILTER_FAIL SECCOMP_RET_TRAP |
| #endif /* SANDBOX_SECCOMP_FILTER_DEBUG */ |
| |
| /* Simple helpers to avoid manual errors (but larger BPF programs). */ |
| #define SC_DENY(_nr, _errno) \ |
| BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \ |
| BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno)) |
| #define SC_ALLOW(_nr) \ |
| BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \ |
| BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) |
| |
| #if defined(__i386__) |
| # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386 |
| #elif defined(__x86_64__) |
| # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64 |
| #elif defined(__arm__) |
| # ifndef EM_ARM |
| # define EM_ARM 40 |
| # endif |
| # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM |
| #elif defined(__aarch64__) |
| # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64 |
| #elif defined(__mips__) |
| # if defined(__MIPSEL__) |
| # if defined(__LP64__) |
| # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL64 |
| # else |
| # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL |
| # endif |
| # elif defined(__LP64__) |
| # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS64 |
| # else |
| # define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS |
| # endif |
| #else |
| # error "Platform does not support seccomp filter yet" |
| #endif |
| |
| /* Returns 0 if the the sandbox is enabled using |
| * the time setter policy. |
| */ |
| int |
| enable_setter_seccomp (void) |
| { |
| static const struct sock_filter insns[] = |
| { |
| /* Ensure the syscall arch convention is as expected. */ |
| BPF_STMT (BPF_LD+BPF_W+BPF_ABS, |
| offsetof (struct seccomp_data, arch)), |
| BPF_JUMP (BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_AUDIT_ARCH, 1, 0), |
| BPF_STMT (BPF_RET+BPF_K, SECCOMP_FILTER_FAIL), |
| /* Load the syscall number for checking. */ |
| BPF_STMT (BPF_LD+BPF_W+BPF_ABS, |
| offsetof (struct seccomp_data, nr)), |
| |
| /* Process ALLOWs as quickly as possible */ |
| SC_ALLOW (read), |
| SC_ALLOW (write), |
| SC_ALLOW (pwrite64), |
| |
| SC_ALLOW (settimeofday), |
| SC_ALLOW (ioctl), /* TODO(wad) filter for fd and RTC_SET_TIME */ |
| #ifdef __NR_time /* This is required for x86 systems */ |
| SC_ALLOW (time), |
| #endif |
| |
| #ifdef __NR_lseek |
| SC_ALLOW (lseek), |
| #endif |
| #ifdef __NR_llseek |
| SC_ALLOW (llseek), |
| #endif |
| #ifdef __NR_lseek64 |
| SC_ALLOW (lseek64), |
| #endif |
| SC_ALLOW (close), |
| SC_ALLOW (munmap), |
| |
| SC_ALLOW (exit_group), |
| SC_ALLOW (exit), |
| |
| #ifdef __NR_open |
| SC_DENY (open, EINVAL), |
| #endif |
| #ifdef __NR_openat |
| SC_DENY (openat, EINVAL), |
| #endif |
| SC_DENY (fcntl, EINVAL), |
| #ifdef __NR_fstat |
| SC_DENY (fstat, EINVAL), |
| #endif |
| #ifdef __NR_fstatat |
| SC_DENY (fstatat, EINVAL), |
| #endif |
| #ifdef __NR_newfstatat |
| SC_DENY (newfstatat, EINVAL), |
| #endif |
| #ifdef __NR_mmap |
| SC_DENY (mmap, EINVAL), |
| #endif |
| #ifdef __NR_mmap2 |
| SC_DENY (mmap2, EINVAL), |
| #endif |
| #ifdef __NR_sendto |
| SC_DENY (sendto, EINVAL), |
| #endif |
| #ifdef __NR_socket |
| SC_DENY (socket, EINVAL), |
| #endif |
| #ifdef __NR_socketcall |
| SC_DENY (socketcall, EINVAL), |
| #endif |
| BPF_STMT (BPF_RET+BPF_K, SECCOMP_FILTER_FAIL), |
| }; |
| static const struct sock_fprog prog = |
| { |
| .len = (unsigned short) (sizeof (insns) /sizeof (insns[0])), |
| .filter = (struct sock_filter *) insns, |
| }; |
| return (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) || |
| prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)); |
| } |