summaryrefslogtreecommitdiffstats
path: root/security/sandbox/linux/SandboxFilterUtil.h
blob: 6e9180bb9524d57ff4197dfe197bcc3b524335c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_SandboxFilterUtil_h
#define mozilla_SandboxFilterUtil_h

// This header file exists to hold helper code for SandboxFilter.cpp,
// to make that file easier to read for anyone trying to understand
// the filter policy.  It's mostly about smoothing out differences
// between different Linux architectures.

#include "mozilla/Maybe.h"
#include "sandbox/linux/bpf_dsl/policy.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"

namespace mozilla {

// This class handles syscalls for BSD socket and SysV IPC operations.
// On 32-bit x86 they're multiplexed via socketcall(2) and ipc(2),
// respectively; on most other architectures they're individual system
// calls. It translates the syscalls into socketcall/ipc selector
// values, because those are defined (even if not used) for all
// architectures.  (As of kernel 4.2.0, x86 also has regular system
// calls, but userland will typically still use socketcall.)
//
// This EvaluateSyscall() routine always returns InvalidSyscall() for
// everything else.  It's assumed that subclasses will be implementing
// a whitelist policy, so they can handle what they're whitelisting
// and then defer to this class in the default case.
class SandboxPolicyBase : public sandbox::bpf_dsl::Policy {
 public:
  using ResultExpr = sandbox::bpf_dsl::ResultExpr;

  virtual ResultExpr EvaluateSyscall(int aSysno) const override;

  // aHasArgs is true if this is a normal syscall, where the arguments
  // can be inspected by seccomp-bpf, rather than a case of socketcall().
  virtual Maybe<ResultExpr> EvaluateSocketCall(int aCall, bool aHasArgs) const {
    return Nothing();
  }

  // Android doesn't use SysV IPC (and doesn't define the selector
  // constants in its headers), so this isn't implemented there.
#ifndef ANDROID
  // aArgShift is the offset to add the argument index when
  // constructing `Arg` objects: it's 0 for separate syscalls and 1
  // for ipc().
  virtual Maybe<ResultExpr> EvaluateIpcCall(int aCall, int aArgShift) const {
    return Nothing();
  }
#endif

  // Returns true if the running kernel supports separate syscalls for
  // socket operations, or false if it supports only socketcall(2).
  static bool HasSeparateSocketCalls();
};

}  // namespace mozilla

// "Machine independent" pseudo-syscall numbers, to deal with arch
// dependencies.  (Most 32-bit archs started with 32-bit off_t; older
// archs started with 16-bit uid_t/gid_t; 32-bit registers can't hold
// a 64-bit offset for mmap; and so on.)
//
// For some of these, the "old" syscalls are also in use in some
// cases; see, e.g., the handling of RT vs. non-RT signal syscalls.

#ifdef __NR_mmap2
#  define CASES_FOR_mmap case __NR_mmap2
#else
#  define CASES_FOR_mmap case __NR_mmap
#endif

#ifdef __NR_fchown32
#  define CASES_FOR_fchown \
    case __NR_fchown32:    \
    case __NR_fchown
#else
#  define CASES_FOR_fchown case __NR_fchown
#endif

#ifdef __NR_getuid32
#  define CASES_FOR_getuid case __NR_getuid32
#  define CASES_FOR_getgid case __NR_getgid32
#  define CASES_FOR_geteuid case __NR_geteuid32
#  define CASES_FOR_getegid case __NR_getegid32
#  define CASES_FOR_getresuid \
    case __NR_getresuid32:    \
    case __NR_getresuid
#  define CASES_FOR_getresgid \
    case __NR_getresgid32:    \
    case __NR_getresgid
// The set*id syscalls are omitted; we'll probably never need to allow them.
#else
#  define CASES_FOR_getuid case __NR_getuid
#  define CASES_FOR_getgid case __NR_getgid
#  define CASES_FOR_geteuid case __NR_geteuid
#  define CASES_FOR_getegid case __NR_getegid
#  define CASES_FOR_getresuid case __NR_getresuid
#  define CASES_FOR_getresgid case __NR_getresgid
#endif

#ifdef __NR_stat64
#  define CASES_FOR_stat case __NR_stat64
#  define CASES_FOR_lstat case __NR_lstat64
#  define CASES_FOR_fstat case __NR_fstat64
#  define CASES_FOR_fstatat case __NR_fstatat64
#  define CASES_FOR_statfs \
    case __NR_statfs64:    \
    case __NR_statfs
#  define CASES_FOR_fstatfs \
    case __NR_fstatfs64:    \
    case __NR_fstatfs
#  define CASES_FOR_fcntl case __NR_fcntl64
// FIXME: we might not need the compat cases for these on non-Android:
#  define CASES_FOR_lseek \
    case __NR_lseek:      \
    case __NR__llseek
#  define CASES_FOR_ftruncate \
    case __NR_ftruncate:      \
    case __NR_ftruncate64
#else
#  define CASES_FOR_stat case __NR_stat
#  define CASES_FOR_lstat case __NR_lstat
#  define CASES_FOR_fstatat case __NR_newfstatat
#  define CASES_FOR_fstat case __NR_fstat
#  define CASES_FOR_fstatfs case __NR_fstatfs
#  define CASES_FOR_statfs case __NR_statfs
#  define CASES_FOR_fcntl case __NR_fcntl
#  define CASES_FOR_lseek case __NR_lseek
#  define CASES_FOR_ftruncate case __NR_ftruncate
#endif

// getdents is not like the other FS-related syscalls with a "64" variant
#ifdef __NR_getdents
#  define CASES_FOR_getdents \
    case __NR_getdents64:    \
    case __NR_getdents
#else
#  define CASES_FOR_getdents case __NR_getdents64
#endif

#ifdef __NR_sigprocmask
#  define CASES_FOR_sigprocmask \
    case __NR_sigprocmask:      \
    case __NR_rt_sigprocmask
#  define CASES_FOR_sigaction \
    case __NR_sigaction:      \
    case __NR_rt_sigaction
#  define CASES_FOR_sigreturn \
    case __NR_sigreturn:      \
    case __NR_rt_sigreturn
#else
#  define CASES_FOR_sigprocmask case __NR_rt_sigprocmask
#  define CASES_FOR_sigaction case __NR_rt_sigaction
#  define CASES_FOR_sigreturn case __NR_rt_sigreturn
#endif

#ifdef __NR_clock_gettime64
#  define CASES_FOR_clock_gettime \
    case __NR_clock_gettime:      \
    case __NR_clock_gettime64
#  define CASES_FOR_clock_getres \
    case __NR_clock_getres:      \
    case __NR_clock_getres_time64
#  define CASES_FOR_clock_nanosleep \
    case __NR_clock_nanosleep:      \
    case __NR_clock_nanosleep_time64
#  define CASES_FOR_pselect6 \
    case __NR_pselect6:      \
    case __NR_pselect6_time64
#  define CASES_FOR_ppoll \
    case __NR_ppoll:      \
    case __NR_ppoll_time64
#  define CASES_FOR_futex \
    case __NR_futex:      \
    case __NR_futex_time64
#else
#  define CASES_FOR_clock_gettime case __NR_clock_gettime
#  define CASES_FOR_clock_getres case __NR_clock_getres
#  define CASES_FOR_clock_nanosleep case __NR_clock_nanosleep
#  define CASES_FOR_pselect6 case __NR_pselect6
#  define CASES_FOR_ppoll case __NR_ppoll
#  define CASES_FOR_futex case __NR_futex
#endif

#if defined(__NR__newselect)
#  define CASES_FOR_select \
    case __NR__newselect:  \
      CASES_FOR_pselect6
#elif defined(__NR_select)
#  define CASES_FOR_select \
    case __NR_select:      \
      CASES_FOR_pselect6
#else
#  define CASES_FOR_select CASES_FOR_pselect6
#endif

#ifdef __NR_poll
#  define CASES_FOR_poll \
    case __NR_poll:      \
      CASES_FOR_ppoll
#else
#  define CASES_FOR_poll CASES_FOR_ppoll
#endif

#ifdef __NR_epoll_create
#  define CASES_FOR_epoll_create \
    case __NR_epoll_create:      \
    case __NR_epoll_create1
#else
#  define CASES_FOR_epoll_create case __NR_epoll_create1
#endif

#ifdef __NR_epoll_wait
#  define CASES_FOR_epoll_wait \
    case __NR_epoll_wait:      \
    case __NR_epoll_pwait
#else
#  define CASES_FOR_epoll_wait case __NR_epoll_pwait
#endif

#ifdef __NR_pipe
#  define CASES_FOR_pipe \
    case __NR_pipe:      \
    case __NR_pipe2
#else
#  define CASES_FOR_pipe case __NR_pipe2
#endif

#ifdef __NR_dup2
#  define CASES_FOR_dup2 \
    case __NR_dup2:      \
    case __NR_dup3
#else
#  define CASES_FOR_dup2 case __NR_dup3
#endif

#ifdef __NR_ugetrlimit
#  define CASES_FOR_getrlimit case __NR_ugetrlimit
#else
#  define CASES_FOR_getrlimit case __NR_getrlimit
#endif

#endif  // mozilla_SandboxFilterUtil_h