1/*
2 * seccomp.c - seccomp utility functions
3 * Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "config.h"
9
10#include <asm/unistd.h>
11#include <elf.h>
12#include <errno.h>
13#include <sys/prctl.h>
14#include <stddef.h>
15#include <stdint.h>
16#include <stdlib.h>
17#include <sys/syscall.h>
18#include <unistd.h>
19
20#include <linux/audit.h>
21#include <linux/filter.h>
22
23#include "src/seccomp.h"
24
25/* Linux seccomp_filter sandbox */
26#define SECCOMP_FILTER_FAIL SECCOMP_RET_KILL
27
28/* Use a signal handler to emit violations when debugging */
29#ifdef SECCOMP_FILTER_DEBUG
30#  undef SECCOMP_FILTER_FAIL
31#  define SECCOMP_FILTER_FAIL SECCOMP_RET_TRAP
32#endif /* SANDBOX_SECCOMP_FILTER_DEBUG */
33
34/* Simple helpers to avoid manual errors (but larger BPF programs). */
35#define SC_DENY(_nr, _errno) \
36  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \
37  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO|(_errno))
38#define SC_ALLOW(_nr) \
39  BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_ ## _nr, 0, 1), \
40  BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
41
42#if defined(__i386__)
43#  define SECCOMP_AUDIT_ARCH AUDIT_ARCH_I386
44#elif defined(__x86_64__)
45#  define SECCOMP_AUDIT_ARCH AUDIT_ARCH_X86_64
46#elif defined(__arm__)
47#  ifndef EM_ARM
48#    define EM_ARM 40
49#  endif
50#  define SECCOMP_AUDIT_ARCH AUDIT_ARCH_ARM
51#elif defined(__aarch64__)
52#  define SECCOMP_AUDIT_ARCH AUDIT_ARCH_AARCH64
53#elif defined(__mips__)
54#  if defined(__MIPSEL__)
55#    if defined(__LP64__)
56#      define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL64
57#    else
58#      define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPSEL
59#    endif
60#  elif defined(__LP64__)
61#    define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS64
62#  else
63#    define SECCOMP_AUDIT_ARCH AUDIT_ARCH_MIPS
64#  endif
65#else
66#  error "Platform does not support seccomp filter yet"
67#endif
68
69/* Returns 0 if the the sandbox is enabled using
70 * the time setter policy.
71 */
72int
73enable_setter_seccomp (void)
74{
75  static const struct sock_filter insns[] =
76  {
77    /* Ensure the syscall arch convention is as expected. */
78    BPF_STMT (BPF_LD+BPF_W+BPF_ABS,
79    offsetof (struct seccomp_data, arch)),
80    BPF_JUMP (BPF_JMP+BPF_JEQ+BPF_K, SECCOMP_AUDIT_ARCH, 1, 0),
81    BPF_STMT (BPF_RET+BPF_K, SECCOMP_FILTER_FAIL),
82    /* Load the syscall number for checking. */
83    BPF_STMT (BPF_LD+BPF_W+BPF_ABS,
84    offsetof (struct seccomp_data, nr)),
85
86    /* Process ALLOWs as quickly as possible */
87    SC_ALLOW (read),
88    SC_ALLOW (write),
89    SC_ALLOW (pwrite64),
90
91    SC_ALLOW (settimeofday),
92    SC_ALLOW (ioctl), /* TODO(wad) filter for fd and RTC_SET_TIME */
93#ifdef __NR_time /* This is required for x86 systems */
94    SC_ALLOW (time),
95#endif
96
97#ifdef __NR_lseek
98    SC_ALLOW (lseek),
99#endif
100#ifdef __NR_llseek
101    SC_ALLOW (llseek),
102#endif
103#ifdef __NR_lseek64
104    SC_ALLOW (lseek64),
105#endif
106    SC_ALLOW (close),
107    SC_ALLOW (munmap),
108
109    SC_ALLOW (exit_group),
110    SC_ALLOW (exit),
111
112#ifdef __NR_open
113    SC_DENY (open, EINVAL),
114#endif
115#ifdef __NR_openat
116    SC_DENY (openat, EINVAL),
117#endif
118    SC_DENY (fcntl, EINVAL),
119#ifdef __NR_fstat
120    SC_DENY (fstat, EINVAL),
121#endif
122#ifdef __NR_fstatat
123    SC_DENY (fstatat, EINVAL),
124#endif
125#ifdef __NR_newfstatat
126    SC_DENY (newfstatat, EINVAL),
127#endif
128#ifdef __NR_mmap
129    SC_DENY (mmap, EINVAL),
130#endif
131#ifdef __NR_mmap2
132    SC_DENY (mmap2, EINVAL),
133#endif
134#ifdef __NR_sendto
135    SC_DENY (sendto, EINVAL),
136#endif
137#ifdef __NR_socket
138    SC_DENY (socket, EINVAL),
139#endif
140#ifdef __NR_socketcall
141    SC_DENY (socketcall, EINVAL),
142#endif
143    BPF_STMT (BPF_RET+BPF_K, SECCOMP_FILTER_FAIL),
144  };
145  static const struct sock_fprog prog =
146  {
147    .len = (unsigned short) (sizeof (insns) /sizeof (insns[0])),
148    .filter = (struct sock_filter *) insns,
149  };
150  return (prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) ||
151          prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog));
152}
153