Coverage Report

Created: 2025-12-12 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/tor/src/lib/sandbox/sandbox.c
Line
Count
Source
1
/* Copyright (c) 2001 Matej Pfajfar.
2
 * Copyright (c) 2001-2004, Roger Dingledine.
3
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4
 * Copyright (c) 2007-2021, The Tor Project, Inc. */
5
/* See LICENSE for licensing information */
6
7
/**
8
 * \file sandbox.c
9
 * \brief Code to enable sandboxing.
10
 **/
11
12
#include "orconfig.h"
13
14
#ifndef _LARGEFILE64_SOURCE
15
/**
16
 * Temporarily required for O_LARGEFILE flag. Needs to be removed
17
 * with the libevent fix.
18
 */
19
#define _LARGEFILE64_SOURCE
20
#endif /* !defined(_LARGEFILE64_SOURCE) */
21
22
/** Malloc mprotect limit in bytes.
23
 *
24
 * 28/06/2017: This value was increased from 16 MB to 20 MB after we introduced
25
 * LZMA support in Tor (0.3.1.1-alpha). We limit our LZMA coder to 16 MB, but
26
 * liblzma have a small overhead that we need to compensate for to avoid being
27
 * killed by the sandbox.
28
 */
29
#define MALLOC_MP_LIM (20*1024*1024)
30
31
#include <stdio.h>
32
#include <string.h>
33
#include <stdlib.h>
34
#include <errno.h>
35
36
#include "lib/sandbox/sandbox.h"
37
#include "lib/container/map.h"
38
#include "lib/err/torerr.h"
39
#include "lib/log/log.h"
40
#include "lib/cc/torint.h"
41
#include "lib/malloc/malloc.h"
42
#include "lib/string/scanf.h"
43
44
#include "ext/tor_queue.h"
45
#include "ext/ht.h"
46
#include "ext/siphash.h"
47
48
#define DEBUGGING_CLOSE
49
50
#if defined(USE_LIBSECCOMP)
51
52
#include <sys/mman.h>
53
#include <sys/syscall.h>
54
#include <sys/types.h>
55
#include <sys/stat.h>
56
#include <sys/epoll.h>
57
#include <sys/prctl.h>
58
#include <linux/futex.h>
59
#include <sys/file.h>
60
61
#ifdef ENABLE_FRAGILE_HARDENING
62
#include <sys/ptrace.h>
63
#endif
64
65
#include <stdarg.h>
66
#include <seccomp.h>
67
#include <signal.h>
68
#include <unistd.h>
69
#include <fcntl.h>
70
#include <time.h>
71
#include <poll.h>
72
73
#ifdef HAVE_GNU_LIBC_VERSION_H
74
#include <gnu/libc-version.h>
75
#endif
76
#ifdef HAVE_LINUX_NETFILTER_IPV4_H
77
#include <linux/netfilter_ipv4.h>
78
#endif
79
#ifdef HAVE_LINUX_IF_H
80
#include <linux/if.h>
81
#endif
82
#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
83
#include <linux/netfilter_ipv6/ip6_tables.h>
84
#endif
85
86
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
87
  defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
88
#define USE_BACKTRACE
89
#define BACKTRACE_PRIVATE
90
#include "lib/err/backtrace.h"
91
#endif /* defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && ... */
92
93
#ifdef USE_BACKTRACE
94
#include <execinfo.h>
95
#endif
96
97
/**
98
 * Linux 32 bit definitions
99
 */
100
#if defined(__i386__)
101
102
#define REG_SYSCALL REG_EAX
103
#define M_SYSCALL gregs[REG_SYSCALL]
104
105
/**
106
 * Linux 64 bit definitions
107
 */
108
#elif defined(__x86_64__)
109
110
#define REG_SYSCALL REG_RAX
111
#define M_SYSCALL gregs[REG_SYSCALL]
112
113
#elif defined(__arm__)
114
115
#define M_SYSCALL arm_r7
116
117
#elif defined(__aarch64__) && defined(__LP64__)
118
119
#define REG_SYSCALL 8
120
#define M_SYSCALL regs[REG_SYSCALL]
121
122
#endif /* defined(__i386__) || ... */
123
124
#ifdef M_SYSCALL
125
#define SYSCALL_NAME_DEBUGGING
126
#endif
127
128
/**
129
 * On newer architectures Linux provides a standardized, generic set of system
130
 * calls (defined in Linux's include/uapi/asm-generic/unistd.h), which omits a
131
 * number of legacy calls used by glibc on other platforms.
132
 */
133
#if defined(__aarch64__) || defined(__riscv)
134
#define ARCH_USES_GENERIC_SYSCALLS
135
#endif
136
137
/**Determines if at least one sandbox is active.*/
138
static int sandbox_active = 0;
139
/** Holds the parameter list configuration for the sandbox.*/
140
static sandbox_cfg_t *filter_dynamic = NULL;
141
142
#undef SCMP_CMP
143
#define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
144
#define SCMP_CMP_STR(a,b,c) \
145
  ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0})
146
#define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
147
/* We use a wrapper here because these masked comparisons seem to be pretty
148
 * verbose. Also, it's important to cast to scmp_datum_t before negating the
149
 * mask, since otherwise the negation might get applied to a 32 bit value, and
150
 * the high bits of the value might get masked out improperly. */
151
#define SCMP_CMP_MASKED(a,b,c) \
152
  SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
153
/* Negative constants aren't consistently sign extended or zero extended.
154
 * Different compilers, libc, and architectures behave differently. For cases
155
 * where the kernel ABI uses a 32 bit integer, this macro can be used to
156
 * mask-compare only the lower 32 bits of the value. */
157
#define SCMP_CMP_LOWER32_EQ(a,b) \
158
  SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, 0xFFFFFFFF, (unsigned int)(b))
159
160
/** Variable used for storing all syscall numbers that will be allowed with the
161
 * stage 1 general Tor sandbox.
162
 */
163
static int filter_nopar_gen[] = {
164
    SCMP_SYS(access),
165
    SCMP_SYS(brk),
166
#ifdef __NR_clock_gettime64
167
    SCMP_SYS(clock_gettime64),
168
#else
169
    SCMP_SYS(clock_gettime),
170
#endif
171
    SCMP_SYS(close),
172
    SCMP_SYS(clone),
173
    SCMP_SYS(dup),
174
#ifdef __NR_clone3
175
    SCMP_SYS(clone3),
176
#endif
177
    SCMP_SYS(epoll_create),
178
    SCMP_SYS(epoll_wait),
179
#ifdef __NR_epoll_pwait
180
    SCMP_SYS(epoll_pwait),
181
#endif
182
#ifdef HAVE_EVENTFD
183
    SCMP_SYS(eventfd2),
184
#endif
185
#ifdef HAVE_PIPE2
186
    SCMP_SYS(pipe2),
187
#endif
188
#ifdef HAVE_PIPE
189
    SCMP_SYS(pipe),
190
#endif
191
#ifdef __NR_fchmod
192
    SCMP_SYS(fchmod),
193
#endif
194
    SCMP_SYS(fcntl),
195
    SCMP_SYS(fstat),
196
#ifdef __NR_fstat64
197
    SCMP_SYS(fstat64),
198
#endif
199
    SCMP_SYS(fsync),
200
    SCMP_SYS(futex),
201
    SCMP_SYS(getdents),
202
    SCMP_SYS(getdents64),
203
    SCMP_SYS(getegid),
204
#ifdef __NR_getegid32
205
    SCMP_SYS(getegid32),
206
#endif
207
    SCMP_SYS(geteuid),
208
#ifdef __NR_geteuid32
209
    SCMP_SYS(geteuid32),
210
#endif
211
    SCMP_SYS(getgid),
212
#ifdef __NR_getgid32
213
    SCMP_SYS(getgid32),
214
#endif
215
    SCMP_SYS(getpid),
216
#ifdef ENABLE_FRAGILE_HARDENING
217
    SCMP_SYS(getppid),
218
#endif
219
#ifdef __NR_getrlimit
220
    SCMP_SYS(getrlimit),
221
#endif
222
    SCMP_SYS(gettimeofday),
223
    SCMP_SYS(gettid),
224
    SCMP_SYS(getuid),
225
#ifdef __NR_getuid32
226
    SCMP_SYS(getuid32),
227
#endif
228
    SCMP_SYS(lseek),
229
#ifdef __NR__llseek
230
    SCMP_SYS(_llseek),
231
#endif
232
    // glob uses this..
233
    SCMP_SYS(lstat),
234
#ifdef __NR_membarrier
235
    /* Inter-processor synchronization, needed for tracing support */
236
    SCMP_SYS(membarrier),
237
#endif
238
    SCMP_SYS(mkdir),
239
    SCMP_SYS(mlockall),
240
#ifdef __NR_mmap
241
    /* XXXX restrict this in the same ways as mmap2 */
242
    SCMP_SYS(mmap),
243
#endif
244
    SCMP_SYS(munmap),
245
#ifdef __NR_nanosleep
246
    SCMP_SYS(nanosleep),
247
#endif
248
#ifdef __NR_prlimit
249
    SCMP_SYS(prlimit),
250
#endif
251
#ifdef __NR_prlimit64
252
    SCMP_SYS(prlimit64),
253
#endif
254
    SCMP_SYS(read),
255
    SCMP_SYS(rt_sigreturn),
256
#ifdef __NR_rseq
257
    SCMP_SYS(rseq),
258
#endif
259
    SCMP_SYS(sched_getaffinity),
260
#ifdef __NR_sched_yield
261
    SCMP_SYS(sched_yield),
262
#endif
263
    SCMP_SYS(sendmsg),
264
    SCMP_SYS(set_robust_list),
265
#ifdef __NR_setrlimit
266
    SCMP_SYS(setrlimit),
267
#endif
268
    SCMP_SYS(shutdown),
269
#ifdef __NR_sigaltstack
270
    SCMP_SYS(sigaltstack),
271
#endif
272
#ifdef __NR_sigreturn
273
    SCMP_SYS(sigreturn),
274
#endif
275
#if defined(__NR_stat)
276
    SCMP_SYS(stat),
277
#elif defined(__i386__) && defined(__NR_statx)
278
    SCMP_SYS(statx),
279
#endif
280
    SCMP_SYS(uname),
281
    SCMP_SYS(wait4),
282
    SCMP_SYS(write),
283
    SCMP_SYS(writev),
284
    SCMP_SYS(exit_group),
285
    SCMP_SYS(exit),
286
287
    SCMP_SYS(madvise),
288
#ifdef __NR_stat64
289
    // getaddrinfo uses this..
290
    SCMP_SYS(stat64),
291
#endif
292
#ifdef __NR_lstat64
293
    // glob uses this on i386 with glibc 2.36+
294
    SCMP_SYS(lstat64),
295
#endif
296
297
#ifdef __NR_getrandom
298
    SCMP_SYS(getrandom),
299
#endif
300
301
#ifdef __NR_sysinfo
302
    // qsort uses this..
303
    SCMP_SYS(sysinfo),
304
#endif
305
    /*
306
     * These socket syscalls are not required on x86_64 and not supported with
307
     * some libseccomp versions (eg: 1.0.1)
308
     */
309
#if defined(__i386)
310
    SCMP_SYS(recv),
311
    SCMP_SYS(send),
312
#endif
313
314
    // socket syscalls
315
    SCMP_SYS(bind),
316
    SCMP_SYS(listen),
317
    SCMP_SYS(connect),
318
    SCMP_SYS(getsockname),
319
#ifdef ENABLE_NSS
320
#ifdef __NR_getpeername
321
    SCMP_SYS(getpeername),
322
#endif
323
#endif
324
    SCMP_SYS(recvmsg),
325
    SCMP_SYS(recvfrom),
326
    SCMP_SYS(sendto),
327
    SCMP_SYS(unlink),
328
#ifdef __NR_unlinkat
329
    SCMP_SYS(unlinkat),
330
#endif
331
    SCMP_SYS(poll)
332
};
333
334
/* opendir is not a syscall but it will use either open or openat. We do not
335
 * want the decision to allow open/openat to be the callers reponsability, so
336
 * we create a phony syscall number for opendir and sb_opendir will choose the
337
 * correct syscall. */
338
#define PHONY_OPENDIR_SYSCALL -2
339
340
/* These macros help avoid the error where the number of filters we add on a
341
 * single rule don't match the arg_cnt param. */
342
#define seccomp_rule_add_0(ctx,act,call) \
343
  seccomp_rule_add((ctx),(act),(call),0)
344
#define seccomp_rule_add_1(ctx,act,call,f1) \
345
  seccomp_rule_add((ctx),(act),(call),1,(f1))
346
#define seccomp_rule_add_2(ctx,act,call,f1,f2)  \
347
  seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
348
#define seccomp_rule_add_3(ctx,act,call,f1,f2,f3)       \
349
  seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
350
#define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4)      \
351
  seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))
352
#define seccomp_rule_add_5(ctx,act,call,f1,f2,f3,f4,f5)       \
353
  seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4),(f5))
354
355
static const char *sandbox_get_interned_string(const char *str);
356
357
/**
358
 * Function responsible for setting up the rt_sigaction syscall for
359
 * the seccomp filter sandbox.
360
 */
361
static int
362
sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
363
{
364
  unsigned i;
365
  int rc;
366
  int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD,
367
                  SIGSEGV, SIGILL, SIGFPE, SIGBUS, SIGSYS, SIGIO,
368
#ifdef SIGXFSZ
369
      SIGXFSZ
370
#endif
371
      };
372
  (void) filter;
373
374
  for (i = 0; i < ARRAY_LENGTH(param); i++) {
375
    rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction),
376
        SCMP_CMP(0, SCMP_CMP_EQ, param[i]));
377
    if (rc)
378
      break;
379
  }
380
381
  return rc;
382
}
383
384
#ifdef __NR_time
385
/**
386
 * Function responsible for setting up the time syscall for
387
 * the seccomp filter sandbox.
388
 */
389
static int
390
sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
391
{
392
  (void) filter;
393
394
  return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time),
395
       SCMP_CMP(0, SCMP_CMP_EQ, 0));
396
}
397
#endif /* defined(__NR_time) */
398
399
/**
400
 * Function responsible for setting up the accept4 syscall for
401
 * the seccomp filter sandbox.
402
 */
403
static int
404
sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
405
{
406
  int rc = 0;
407
  (void)filter;
408
409
#ifdef __i386__
410
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall),
411
      SCMP_CMP(0, SCMP_CMP_EQ, 18));
412
  if (rc) {
413
    return rc;
414
  }
415
#endif /* defined(__i386__) */
416
417
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
418
                   SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
419
  if (rc) {
420
    return rc;
421
  }
422
423
  return 0;
424
}
425
426
#ifdef __NR_mmap2
427
/**
428
 * Function responsible for setting up the mmap2 syscall for
429
 * the seccomp filter sandbox.
430
 */
431
static int
432
sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
433
{
434
  int rc = 0;
435
  (void)filter;
436
437
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
438
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ),
439
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE));
440
  if (rc) {
441
    return rc;
442
  }
443
444
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
445
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
446
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE));
447
  if (rc) {
448
    return rc;
449
  }
450
451
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
452
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
453
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS));
454
  if (rc) {
455
    return rc;
456
  }
457
458
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
459
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
460
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
461
  if (rc) {
462
    return rc;
463
  }
464
465
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
466
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
467
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
468
  if (rc) {
469
    return rc;
470
  }
471
472
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
473
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
474
      SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE));
475
  if (rc) {
476
    return rc;
477
  }
478
479
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
480
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
481
      SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS));
482
  if (rc) {
483
    return rc;
484
  }
485
486
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
487
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC),
488
      SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE));
489
  if (rc) {
490
    return rc;
491
  }
492
493
  return 0;
494
}
495
#endif /* defined(__NR_mmap2) */
496
497
#ifdef HAVE_GNU_LIBC_VERSION_H
498
#ifdef HAVE_GNU_GET_LIBC_VERSION
499
#define CHECK_LIBC_VERSION
500
#endif
501
#endif
502
503
/* Return true the libc version is greater or equal than
504
 * <b>major</b>.<b>minor</b>. Returns false otherwise. */
505
static int
506
is_libc_at_least(int major, int minor)
507
{
508
#ifdef CHECK_LIBC_VERSION
509
  const char *version = gnu_get_libc_version();
510
  if (version == NULL)
511
    return 0;
512
513
  int libc_major = -1;
514
  int libc_minor = -1;
515
516
  tor_sscanf(version, "%d.%d", &libc_major, &libc_minor);
517
  if (libc_major > major)
518
    return 1;
519
  else if (libc_major == major && libc_minor >= minor)
520
    return 1;
521
  else
522
    return 0;
523
#else /* !defined(CHECK_LIBC_VERSION) */
524
  (void)major;
525
  (void)minor;
526
  return 0;
527
#endif /* defined(CHECK_LIBC_VERSION) */
528
}
529
530
/* Return true if we think we're running with a libc that uses openat for the
531
 * open function on linux. */
532
static int
533
libc_uses_openat_for_open(void)
534
{
535
#ifdef __NR_open
536
  return is_libc_at_least(2, 26);
537
#else
538
  return 1;
539
#endif /* defined(__NR_open) */
540
}
541
542
/* Calls to opendir() cannot be filtered by the sandbox when built with fragile
543
 * hardening for an architecture that uses Linux's generic syscall interface,
544
 * so prevent a compiler warning by omitting this function along with
545
 * sb_opendir(). */
546
#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
547
/* Return true if we think we're running with a libc that uses openat for the
548
 * opendir function on linux. */
549
static int
550
libc_uses_openat_for_opendir(void)
551
{
552
#ifdef __NR_open
553
  // libc 2.27 and above or between 2.15 (inclusive) and 2.22 (exclusive)
554
  return is_libc_at_least(2, 27) ||
555
         (is_libc_at_least(2, 15) && !is_libc_at_least(2, 22));
556
#else
557
  return 1;
558
#endif /* defined(__NR_open) */
559
}
560
#endif /* !(defined(ENABLE_FRAGILE_HARDENING) &&
561
            defined(ARCH_USES_GENERIC_SYSCALLS)) */
562
563
/** Allow a single file to be opened.  If <b>use_openat</b> is true,
564
 * we're using a libc that remaps all the opens into openats. */
565
static int
566
allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file)
567
{
568
  if (use_openat) {
569
    return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
570
                              SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
571
                              SCMP_CMP_STR(1, SCMP_CMP_EQ, file));
572
  } else {
573
    return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
574
                              SCMP_CMP_STR(0, SCMP_CMP_EQ, file));
575
  }
576
}
577
578
/**
579
 * Function responsible for setting up the open syscall for
580
 * the seccomp filter sandbox.
581
 */
582
static int
583
sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
584
{
585
  int rc;
586
  sandbox_cfg_t *elem = NULL;
587
588
  int use_openat = libc_uses_openat_for_open();
589
590
#ifdef ENABLE_FRAGILE_HARDENING
591
  /* AddressSanitizer uses either the "open" or the "openat" syscall (depending
592
   * on the architecture) to access information about the running process via
593
   * the filesystem, so the appropriate call must be allowed without
594
   * restriction or the sanitizer will be unable to execute normally when the
595
   * process terminates. */
596
#ifdef ARCH_USES_GENERIC_SYSCALLS
597
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
598
      SCMP_CMP_LOWER32_EQ(0, AT_FDCWD));
599
  if (rc != 0) {
600
    log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
601
        "libseccomp error %d", rc);
602
    return rc;
603
  }
604
605
  /* The "open" syscall is not defined on this architecture, so any other
606
   * requests to open files will necessarily use "openat" as well and there is
607
   * no need to consider any additional rules. */
608
  return 0;
609
#else
610
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open));
611
  if (rc != 0) {
612
    log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
613
        "libseccomp error %d", rc);
614
    return rc;
615
  }
616
617
  /* If glibc also uses only the "open" syscall to open files on this system
618
   * there is no need to consider any additional rules. */
619
  if (!use_openat)
620
    return 0;
621
#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */
622
#endif /* defined(ENABLE_FRAGILE_HARDENING) */
623
624
  // for each dynamic parameter filters
625
  for (elem = filter; elem != NULL; elem = elem->next) {
626
    smp_param_t *param = elem->param;
627
628
    if (param != NULL && param->prot == 1 && param->syscall
629
        == SCMP_SYS(open)) {
630
      rc = allow_file_open(ctx, use_openat, param->value);
631
      if (rc != 0) {
632
        log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
633
            "libseccomp error %d", rc);
634
        return rc;
635
      }
636
    }
637
  }
638
639
  return 0;
640
}
641
642
#ifdef ARCH_USES_GENERIC_SYSCALLS
643
static int
644
sb_fchmodat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
645
{
646
  int rc;
647
  sandbox_cfg_t *elem = NULL;
648
649
  // for each dynamic parameter filters
650
  for (elem = filter; elem != NULL; elem = elem->next) {
651
    smp_param_t *param = elem->param;
652
653
    if (param != NULL && param->prot == 1 && param->syscall
654
        == SCMP_SYS(fchmodat)) {
655
      rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchmodat),
656
          SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
657
          SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
658
      if (rc != 0) {
659
        log_err(LD_BUG,"(Sandbox) failed to add fchmodat syscall, received "
660
            "libseccomp error %d", rc);
661
        return rc;
662
      }
663
    }
664
  }
665
666
  return 0;
667
}
668
#else
669
static int
670
sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
671
{
672
  int rc;
673
  sandbox_cfg_t *elem = NULL;
674
675
  // for each dynamic parameter filters
676
  for (elem = filter; elem != NULL; elem = elem->next) {
677
    smp_param_t *param = elem->param;
678
679
    if (param != NULL && param->prot == 1 && param->syscall
680
        == SCMP_SYS(chmod)) {
681
      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod),
682
            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
683
      if (rc != 0) {
684
        log_err(LD_BUG,"(Sandbox) failed to add chmod syscall, received "
685
            "libseccomp error %d", rc);
686
        return rc;
687
      }
688
    }
689
  }
690
691
  return 0;
692
}
693
#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */
694
695
#if defined(ARCH_USES_GENERIC_SYSCALLS)
696
static int
697
sb_fchownat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
698
{
699
  int rc;
700
  sandbox_cfg_t *elem = NULL;
701
702
  // for each dynamic parameter filters
703
  for (elem = filter; elem != NULL; elem = elem->next) {
704
    smp_param_t *param = elem->param;
705
706
    if (param != NULL && param->prot == 1 && param->syscall
707
        == SCMP_SYS(fchownat)) {
708
      rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fchownat),
709
          SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
710
          SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
711
      if (rc != 0) {
712
        log_err(LD_BUG,"(Sandbox) failed to add fchownat syscall, received "
713
            "libseccomp error %d", rc);
714
        return rc;
715
      }
716
    }
717
  }
718
719
  return 0;
720
}
721
#elif defined(__i386__)
722
static int
723
sb_chown32(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
724
{
725
  int rc;
726
  sandbox_cfg_t *elem = NULL;
727
728
  // for each dynamic parameter filters
729
  for (elem = filter; elem != NULL; elem = elem->next) {
730
    smp_param_t *param = elem->param;
731
732
    if (param != NULL && param->prot == 1 && param->syscall
733
        == SCMP_SYS(chown32)) {
734
      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown32),
735
            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
736
      if (rc != 0) {
737
        log_err(LD_BUG,"(Sandbox) failed to add chown32 syscall, received "
738
            "libseccomp error %d", rc);
739
        return rc;
740
      }
741
    }
742
  }
743
744
  return 0;
745
}
746
#else
747
static int
748
sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
749
{
750
  int rc;
751
  sandbox_cfg_t *elem = NULL;
752
753
  // for each dynamic parameter filters
754
  for (elem = filter; elem != NULL; elem = elem->next) {
755
    smp_param_t *param = elem->param;
756
757
    if (param != NULL && param->prot == 1 && param->syscall
758
        == SCMP_SYS(chown)) {
759
      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown),
760
            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
761
      if (rc != 0) {
762
        log_err(LD_BUG,"(Sandbox) failed to add chown syscall, received "
763
            "libseccomp error %d", rc);
764
        return rc;
765
      }
766
    }
767
  }
768
769
  return 0;
770
}
771
#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) || defined(__i386__) */
772
773
#if defined(__NR_rename)
774
/**
775
 * Function responsible for setting up the rename syscall for
776
 * the seccomp filter sandbox.
777
 */
778
static int
779
sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
780
{
781
  int rc;
782
  sandbox_cfg_t *elem = NULL;
783
784
  // for each dynamic parameter filters
785
  for (elem = filter; elem != NULL; elem = elem->next) {
786
    smp_param_t *param = elem->param;
787
788
    if (param != NULL && param->prot == 1 &&
789
        param->syscall == SCMP_SYS(rename)) {
790
791
      rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
792
            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
793
            SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
794
      if (rc != 0) {
795
        log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
796
            "libseccomp error %d", rc);
797
        return rc;
798
      }
799
    }
800
  }
801
802
  return 0;
803
}
804
#elif defined(__NR_renameat)
805
/**
806
 * Function responsible for setting up the renameat syscall for
807
 * the seccomp filter sandbox.
808
 */
809
static int
810
sb_renameat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
811
{
812
  int rc;
813
  sandbox_cfg_t *elem = NULL;
814
815
  // for each dynamic parameter filters
816
  for (elem = filter; elem != NULL; elem = elem->next) {
817
    smp_param_t *param = elem->param;
818
819
    if (param != NULL && param->prot == 1 &&
820
        param->syscall == SCMP_SYS(renameat)) {
821
822
      rc = seccomp_rule_add_4(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat),
823
            SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
824
            SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
825
            SCMP_CMP_LOWER32_EQ(2, AT_FDCWD),
826
            SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2));
827
      if (rc != 0) {
828
        log_err(LD_BUG,"(Sandbox) failed to add renameat syscall, received "
829
            "libseccomp error %d", rc);
830
        return rc;
831
      }
832
    }
833
  }
834
835
  return 0;
836
}
837
#else
838
/**
839
 * Function responsible for setting up the renameat2 syscall for
840
 * the seccomp filter sandbox.
841
 */
842
static int
843
sb_renameat2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
844
{
845
  int rc;
846
  sandbox_cfg_t *elem = NULL;
847
848
  // for each dynamic parameter filters
849
  for (elem = filter; elem != NULL; elem = elem->next) {
850
    smp_param_t *param = elem->param;
851
852
    if (param != NULL && param->prot == 1 &&
853
        param->syscall == SCMP_SYS(renameat2)) {
854
855
      rc = seccomp_rule_add_5(ctx, SCMP_ACT_ALLOW, SCMP_SYS(renameat2),
856
            SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
857
            SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
858
            SCMP_CMP_LOWER32_EQ(2, AT_FDCWD),
859
            SCMP_CMP_STR(3, SCMP_CMP_EQ, param->value2),
860
            SCMP_CMP(4, SCMP_CMP_EQ, 0));
861
      if (rc != 0) {
862
        log_err(LD_BUG,"(Sandbox) failed to add renameat2 syscall, received "
863
            "libseccomp error %d", rc);
864
        return rc;
865
      }
866
    }
867
  }
868
869
  return 0;
870
}
871
#endif /* defined(__NR_rename) || defined(__NR_renameat) */
872
873
/* If Tor is built with fragile hardening for an architecture that uses Linux's
874
 * generic syscall interface a rule allowing the "openat" syscall without
875
 * restriction will have already been added by sb_open(), so there is no need
876
 * to consider adding additional, more restrictive rules here as they will
877
 * simply be ignored.
878
 *
879
 * Also, since the "open" syscall is not defined on these architectures, glibc
880
 * will necessarily use "openat" for its implementation of opendir() as well.
881
 * This means neither of the following two functions will have any effect and
882
 * both can be omitted. */
883
#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
884
/**
885
 * Function responsible for setting up the openat syscall for
886
 * the seccomp filter sandbox.
887
 */
888
static int
889
sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
890
{
891
  int rc;
892
  sandbox_cfg_t *elem = NULL;
893
894
  // for each dynamic parameter filters
895
  for (elem = filter; elem != NULL; elem = elem->next) {
896
    smp_param_t *param = elem->param;
897
898
    if (param != NULL && param->prot == 1 && param->syscall
899
        == SCMP_SYS(openat)) {
900
      rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
901
          SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
902
          SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
903
          SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|
904
              O_CLOEXEC));
905
      if (rc != 0) {
906
        log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
907
            "libseccomp error %d", rc);
908
        return rc;
909
      }
910
    }
911
  }
912
913
  return 0;
914
}
915
916
static int
917
sb_opendir(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
918
{
919
  int rc;
920
  sandbox_cfg_t *elem = NULL;
921
922
  // for each dynamic parameter filters
923
  for (elem = filter; elem != NULL; elem = elem->next) {
924
    smp_param_t *param = elem->param;
925
926
    if (param != NULL && param->prot == 1 && param->syscall
927
        == PHONY_OPENDIR_SYSCALL) {
928
      rc = allow_file_open(ctx, libc_uses_openat_for_opendir(), param->value);
929
      if (rc != 0) {
930
        log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
931
            "libseccomp error %d", rc);
932
        return rc;
933
      }
934
    }
935
  }
936
937
  return 0;
938
}
939
#endif /* !(defined(ENABLE_FRAGILE_HARDENING) &&
940
            defined(ARCH_USES_GENERIC_SYSCALLS)) */
941
942
#ifdef ENABLE_FRAGILE_HARDENING
943
/**
944
 * Function responsible for setting up the ptrace syscall for
945
 * the seccomp filter sandbox.
946
 */
947
static int
948
sb_ptrace(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
949
{
950
  int rc;
951
  pid_t pid = getpid();
952
  (void) filter;
953
954
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
955
      SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_ATTACH),
956
      SCMP_CMP(1, SCMP_CMP_EQ, pid));
957
  if (rc)
958
    return rc;
959
960
  /* AddressSanitizer uses "PTRACE_GETREGSET" on AArch64 (ARM64) and
961
   * System/390, "PTRACE_GETREGS" everywhere else. */
962
#if defined(__aarch64__) || defined(__s390__)
963
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
964
      SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGSET),
965
      SCMP_CMP(1, SCMP_CMP_EQ, pid));
966
#else
967
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ptrace),
968
      SCMP_CMP(0, SCMP_CMP_EQ, PTRACE_GETREGS),
969
      SCMP_CMP(1, SCMP_CMP_EQ, pid));
970
#endif /* defined(__aarch64__) || defined(__s390__) */
971
  if (rc)
972
    return rc;
973
974
  return 0;
975
}
976
#endif
977
978
/**
979
 * Function responsible for setting up the socket syscall for
980
 * the seccomp filter sandbox.
981
 */
982
static int
983
sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
984
{
985
  int rc = 0;
986
  int i, j;
987
  (void) filter;
988
989
#ifdef __i386__
990
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
991
  if (rc)
992
    return rc;
993
#endif
994
995
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
996
      SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
997
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
998
  if (rc)
999
    return rc;
1000
1001
  for (i = 0; i < 2; ++i) {
1002
    const int pf = i ? PF_INET : PF_INET6;
1003
    for (j=0; j < 3; ++j) {
1004
      const int type     = (j == 0) ? SOCK_STREAM :
1005
                                      SOCK_DGRAM;
1006
      const int protocol = (j == 0) ? IPPROTO_TCP :
1007
                           (j == 1) ? IPPROTO_IP :
1008
                                      IPPROTO_UDP;
1009
      rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1010
        SCMP_CMP(0, SCMP_CMP_EQ, pf),
1011
        SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, type),
1012
        SCMP_CMP(2, SCMP_CMP_EQ, protocol));
1013
      if (rc)
1014
        return rc;
1015
    }
1016
  }
1017
1018
#ifdef ENABLE_NSS
1019
  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1020
    SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
1021
    SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM),
1022
    SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
1023
  if (rc)
1024
    return rc;
1025
#endif /* defined(ENABLE_NSS) */
1026
1027
  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1028
      SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
1029
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
1030
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
1031
  if (rc)
1032
    return rc;
1033
1034
  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1035
      SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
1036
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
1037
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
1038
  if (rc)
1039
    return rc;
1040
1041
  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
1042
      SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
1043
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC, SOCK_RAW),
1044
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
1045
  if (rc)
1046
    return rc;
1047
1048
  return 0;
1049
}
1050
1051
/**
1052
 * Function responsible for setting up the socketpair syscall for
1053
 * the seccomp filter sandbox.
1054
 */
1055
static int
1056
sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1057
{
1058
  int rc = 0;
1059
  (void) filter;
1060
1061
#ifdef __i386__
1062
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair));
1063
  if (rc)
1064
    return rc;
1065
#endif
1066
1067
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair),
1068
      SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
1069
      SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC));
1070
  if (rc)
1071
    return rc;
1072
1073
  return 0;
1074
}
1075
1076
#ifdef HAVE_KIST_SUPPORT
1077
1078
#include <linux/sockios.h>
1079
1080
static int
1081
sb_ioctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1082
{
1083
  int rc;
1084
  (void) filter;
1085
1086
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl),
1087
                          SCMP_CMP(1, SCMP_CMP_EQ, SIOCOUTQNSD));
1088
  if (rc)
1089
    return rc;
1090
  return 0;
1091
}
1092
1093
#endif /* defined(HAVE_KIST_SUPPORT) */
1094
1095
/**
1096
 * Function responsible for setting up the setsockopt syscall for
1097
 * the seccomp filter sandbox.
1098
 */
1099
static int
1100
sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1101
{
1102
  int rc = 0;
1103
  (void) filter;
1104
1105
#ifdef __i386__
1106
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt));
1107
  if (rc)
1108
    return rc;
1109
#endif
1110
1111
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1112
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1113
      SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR));
1114
  if (rc)
1115
    return rc;
1116
1117
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1118
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1119
      SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
1120
  if (rc)
1121
    return rc;
1122
1123
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1124
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1125
      SCMP_CMP(2, SCMP_CMP_EQ, SO_RCVBUF));
1126
  if (rc)
1127
    return rc;
1128
1129
#ifdef HAVE_SYSTEMD
1130
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1131
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1132
      SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUFFORCE));
1133
  if (rc)
1134
    return rc;
1135
#endif /* defined(HAVE_SYSTEMD) */
1136
1137
#ifdef IP_TRANSPARENT
1138
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1139
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
1140
      SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT));
1141
  if (rc)
1142
    return rc;
1143
#endif /* defined(IP_TRANSPARENT) */
1144
1145
#ifdef IPV6_V6ONLY
1146
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1147
      SCMP_CMP(1, SCMP_CMP_EQ, IPPROTO_IPV6),
1148
      SCMP_CMP(2, SCMP_CMP_EQ, IPV6_V6ONLY));
1149
  if (rc)
1150
    return rc;
1151
#endif /* defined(IPV6_V6ONLY) */
1152
1153
#ifdef IP_BIND_ADDRESS_NO_PORT
1154
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
1155
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
1156
      SCMP_CMP(2, SCMP_CMP_EQ, IP_BIND_ADDRESS_NO_PORT));
1157
  if (rc)
1158
    return rc;
1159
#endif
1160
1161
  return 0;
1162
}
1163
1164
/**
1165
 * Function responsible for setting up the getsockopt syscall for
1166
 * the seccomp filter sandbox.
1167
 */
1168
static int
1169
sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1170
{
1171
  int rc = 0;
1172
  (void) filter;
1173
1174
#ifdef __i386__
1175
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt));
1176
  if (rc)
1177
    return rc;
1178
#endif
1179
1180
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1181
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1182
      SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR));
1183
  if (rc)
1184
    return rc;
1185
1186
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1187
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1188
      SCMP_CMP(2, SCMP_CMP_EQ, SO_ACCEPTCONN));
1189
  if (rc)
1190
    return rc;
1191
1192
#ifdef HAVE_SYSTEMD
1193
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1194
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
1195
      SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
1196
  if (rc)
1197
    return rc;
1198
#endif /* defined(HAVE_SYSTEMD) */
1199
1200
#ifdef HAVE_LINUX_NETFILTER_IPV4_H
1201
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1202
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
1203
      SCMP_CMP(2, SCMP_CMP_EQ, SO_ORIGINAL_DST));
1204
  if (rc)
1205
    return rc;
1206
#endif /* defined(HAVE_LINUX_NETFILTER_IPV4_H) */
1207
1208
#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
1209
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1210
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_IPV6),
1211
      SCMP_CMP(2, SCMP_CMP_EQ, IP6T_SO_ORIGINAL_DST));
1212
  if (rc)
1213
    return rc;
1214
#endif /* defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H) */
1215
1216
#ifdef HAVE_KIST_SUPPORT
1217
#include <netinet/tcp.h>
1218
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
1219
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_TCP),
1220
      SCMP_CMP(2, SCMP_CMP_EQ, TCP_INFO));
1221
  if (rc)
1222
    return rc;
1223
#endif /* defined(HAVE_KIST_SUPPORT) */
1224
1225
  return 0;
1226
}
1227
1228
#ifdef __NR_fcntl64
1229
/**
1230
 * Function responsible for setting up the fcntl64 syscall for
1231
 * the seccomp filter sandbox.
1232
 */
1233
static int
1234
sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1235
{
1236
  int rc = 0;
1237
  (void) filter;
1238
1239
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
1240
      SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL));
1241
  if (rc)
1242
    return rc;
1243
1244
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
1245
      SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL),
1246
      SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK));
1247
  if (rc)
1248
    return rc;
1249
1250
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
1251
      SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD));
1252
  if (rc)
1253
    return rc;
1254
1255
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
1256
      SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD),
1257
      SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC));
1258
  if (rc)
1259
    return rc;
1260
1261
  return 0;
1262
}
1263
#endif /* defined(__NR_fcntl64) */
1264
1265
/**
1266
 * Function responsible for setting up the epoll_ctl syscall for
1267
 * the seccomp filter sandbox.
1268
 *
1269
 *  Note: basically allows everything but will keep for now..
1270
 */
1271
static int
1272
sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1273
{
1274
  int rc = 0;
1275
  (void) filter;
1276
1277
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
1278
      SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD));
1279
  if (rc)
1280
    return rc;
1281
1282
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
1283
      SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
1284
  if (rc)
1285
    return rc;
1286
1287
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
1288
      SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
1289
  if (rc)
1290
    return rc;
1291
1292
  return 0;
1293
}
1294
1295
/**
1296
 * Function responsible for setting up the prctl syscall for
1297
 * the seccomp filter sandbox.
1298
 *
1299
 * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs
1300
 * to be allowlisted in this function.
1301
 */
1302
static int
1303
sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1304
{
1305
  int rc = 0;
1306
  (void) filter;
1307
1308
#ifdef ENABLE_FRAGILE_HARDENING
1309
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1310
      SCMP_CMP(0, SCMP_CMP_EQ, PR_GET_DUMPABLE));
1311
  if (rc)
1312
    return rc;
1313
1314
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1315
      SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_PTRACER));
1316
  if (rc)
1317
    return rc;
1318
#endif
1319
1320
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
1321
      SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
1322
  if (rc)
1323
    return rc;
1324
1325
  return 0;
1326
}
1327
1328
/**
1329
 * Function responsible for setting up the mprotect syscall for
1330
 * the seccomp filter sandbox.
1331
 *
1332
 * NOTE: does not NEED to be here.. currently only occurs before filter; will
1333
 * keep just in case for the future.
1334
 */
1335
static int
1336
sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1337
{
1338
  int rc = 0;
1339
  (void) filter;
1340
1341
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1342
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
1343
  if (rc)
1344
    return rc;
1345
1346
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1347
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
1348
  if (rc)
1349
    return rc;
1350
1351
  return 0;
1352
}
1353
1354
/**
1355
 * Function responsible for setting up the rt_sigprocmask syscall for
1356
 * the seccomp filter sandbox.
1357
 */
1358
static int
1359
sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1360
{
1361
  int rc = 0;
1362
  (void) filter;
1363
1364
#if defined(ENABLE_FRAGILE_HARDENING) || \
1365
    defined(USE_TRACING_INSTRUMENTATION_LTTNG)
1366
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1367
      SCMP_CMP(0, SCMP_CMP_EQ, SIG_BLOCK));
1368
  if (rc)
1369
    return rc;
1370
#endif
1371
1372
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1373
      SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
1374
  if (rc)
1375
    return rc;
1376
1377
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
1378
      SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
1379
  if (rc)
1380
    return rc;
1381
1382
  return 0;
1383
}
1384
1385
/**
1386
 * Function responsible for setting up the flock syscall for
1387
 * the seccomp filter sandbox.
1388
 *
1389
 *  NOTE: does not need to be here, occurs before filter is applied.
1390
 */
1391
static int
1392
sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1393
{
1394
  int rc = 0;
1395
  (void) filter;
1396
1397
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1398
      SCMP_CMP(1, SCMP_CMP_EQ, LOCK_EX|LOCK_NB));
1399
  if (rc)
1400
    return rc;
1401
1402
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
1403
      SCMP_CMP(1, SCMP_CMP_EQ, LOCK_UN));
1404
  if (rc)
1405
    return rc;
1406
1407
  return 0;
1408
}
1409
1410
/**
1411
 * Function responsible for setting up the futex syscall for
1412
 * the seccomp filter sandbox.
1413
 */
1414
static int
1415
sb_futex(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1416
{
1417
  int rc = 0;
1418
  (void) filter;
1419
1420
  // can remove
1421
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1422
      SCMP_CMP(1, SCMP_CMP_EQ,
1423
          FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME));
1424
  if (rc)
1425
    return rc;
1426
1427
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1428
      SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAKE_PRIVATE));
1429
  if (rc)
1430
    return rc;
1431
1432
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(futex),
1433
      SCMP_CMP(1, SCMP_CMP_EQ, FUTEX_WAIT_PRIVATE));
1434
  if (rc)
1435
    return rc;
1436
1437
  return 0;
1438
}
1439
1440
/**
1441
 * Function responsible for setting up the mremap syscall for
1442
 * the seccomp filter sandbox.
1443
 *
1444
 *  NOTE: so far only occurs before filter is applied.
1445
 */
1446
static int
1447
sb_mremap(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1448
{
1449
  int rc = 0;
1450
  (void) filter;
1451
1452
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mremap),
1453
      SCMP_CMP(3, SCMP_CMP_EQ, MREMAP_MAYMOVE));
1454
  if (rc)
1455
    return rc;
1456
1457
  return 0;
1458
}
1459
1460
#ifdef ARCH_USES_GENERIC_SYSCALLS
1461
/**
1462
 * Function responsible for setting up the newfstatat syscall for
1463
 * the seccomp filter sandbox.
1464
 */
1465
static int
1466
sb_newfstatat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1467
{
1468
  int rc = 0;
1469
1470
  sandbox_cfg_t *elem = NULL;
1471
1472
  // for each dynamic parameter filters
1473
  for (elem = filter; elem != NULL; elem = elem->next) {
1474
    smp_param_t *param = elem->param;
1475
1476
    if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
1477
        || param->syscall == PHONY_OPENDIR_SYSCALL
1478
        || param->syscall == SCMP_SYS(newfstatat))) {
1479
      rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat),
1480
          SCMP_CMP_LOWER32_EQ(0, AT_FDCWD),
1481
          SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value));
1482
      if (rc != 0) {
1483
        log_err(LD_BUG,"(Sandbox) failed to add newfstatat syscall, received "
1484
            "libseccomp error %d", rc);
1485
        return rc;
1486
      }
1487
    }
1488
  }
1489
1490
  return 0;
1491
}
1492
#endif /* defined(ARCH_USES_GENERIC_SYSCALLS) */
1493
1494
#ifdef __NR_stat64
1495
/**
1496
 * Function responsible for setting up the stat64 syscall for
1497
 * the seccomp filter sandbox.
1498
 */
1499
static int
1500
sb_stat64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1501
{
1502
  int rc = 0;
1503
  sandbox_cfg_t *elem = NULL;
1504
1505
  // for each dynamic parameter filters
1506
  for (elem = filter; elem != NULL; elem = elem->next) {
1507
    smp_param_t *param = elem->param;
1508
1509
    if (param != NULL && param->prot == 1 && (param->syscall == SCMP_SYS(open)
1510
        || param->syscall == SCMP_SYS(stat64))) {
1511
      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(stat64),
1512
          SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
1513
      if (rc != 0) {
1514
        log_err(LD_BUG,"(Sandbox) failed to add stat64 syscall, received "
1515
            "libseccomp error %d", rc);
1516
        return rc;
1517
      }
1518
    }
1519
  }
1520
1521
  return 0;
1522
}
1523
#endif /* defined(__NR_stat64) */
1524
1525
static int
1526
sb_kill(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
1527
{
1528
  (void) filter;
1529
#ifdef __NR_kill
1530
  /* Allow killing anything with signal 0 -- it isn't really a kill. */
1531
  return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(kill),
1532
       SCMP_CMP(1, SCMP_CMP_EQ, 0));
1533
#else
1534
  return 0;
1535
#endif /* defined(__NR_kill) */
1536
}
1537
1538
/**
1539
 * Array of function pointers responsible for filtering different syscalls at
1540
 * a parameter level.
1541
 */
1542
static sandbox_filter_func_t filter_func[] = {
1543
    sb_rt_sigaction,
1544
    sb_rt_sigprocmask,
1545
#ifdef __NR_time
1546
    sb_time,
1547
#endif
1548
    sb_accept4,
1549
#ifdef __NR_mmap2
1550
    sb_mmap2,
1551
#endif
1552
#if defined(ARCH_USES_GENERIC_SYSCALLS)
1553
    sb_fchownat,
1554
#elif defined(__i386__)
1555
    sb_chown32,
1556
#else
1557
    sb_chown,
1558
#endif
1559
#if defined(ARCH_USES_GENERIC_SYSCALLS)
1560
    sb_fchmodat,
1561
#else
1562
    sb_chmod,
1563
#endif
1564
    sb_open,
1565
#if !(defined(ENABLE_FRAGILE_HARDENING) && defined(ARCH_USES_GENERIC_SYSCALLS))
1566
    sb_openat,
1567
    sb_opendir,
1568
#endif
1569
#ifdef ENABLE_FRAGILE_HARDENING
1570
    sb_ptrace,
1571
#endif
1572
#if defined(__NR_rename)
1573
    sb_rename,
1574
#elif defined(__NR_renameat)
1575
    sb_renameat,
1576
#else
1577
    sb_renameat2,
1578
#endif
1579
#ifdef __NR_fcntl64
1580
    sb_fcntl64,
1581
#endif
1582
    sb_epoll_ctl,
1583
    sb_prctl,
1584
    sb_mprotect,
1585
    sb_flock,
1586
    sb_futex,
1587
    sb_mremap,
1588
#if defined(ARCH_USES_GENERIC_SYSCALLS)
1589
    sb_newfstatat,
1590
#elif defined(__NR_stat64)
1591
    sb_stat64,
1592
#endif
1593
1594
    sb_socket,
1595
    sb_setsockopt,
1596
    sb_getsockopt,
1597
    sb_socketpair,
1598
#ifdef HAVE_KIST_SUPPORT
1599
    sb_ioctl,
1600
#endif
1601
    sb_kill
1602
};
1603
1604
/**
1605
 * Return the interned (and hopefully sandbox-permitted) string equal
1606
 * to @a str.
1607
 *
1608
 * Return NULL if `str` is NULL, or `str` is not an interned string.
1609
 **/
1610
const char *
1611
sandbox_intern_string(const char *str)
1612
{
1613
  const char *interned = sandbox_get_interned_string(str);
1614
1615
  if (sandbox_active && str != NULL && interned == NULL) {
1616
    log_warn(LD_BUG, "No interned sandbox parameter found for %s", str);
1617
  }
1618
1619
  return interned ? interned : str;
1620
}
1621
1622
/**
1623
 * Return true if the sandbox is running and we are missing an interned string
1624
 * equal to @a str.
1625
 */
1626
bool
1627
sandbox_interned_string_is_missing(const char *str)
1628
{
1629
  return sandbox_active && sandbox_get_interned_string(str) == NULL;
1630
}
1631
1632
/**
1633
 * Try to find and return the interned string equal to @a str.
1634
 *
1635
 * If there is no such string, return NULL.
1636
 **/
1637
static const char *
1638
sandbox_get_interned_string(const char *str)
1639
{
1640
  sandbox_cfg_t *elem;
1641
1642
  if (str == NULL)
1643
    return NULL;
1644
1645
  for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
1646
    smp_param_t *param = elem->param;
1647
1648
    if (param->prot) {
1649
      if (!strcmp(str, (char*)(param->value))) {
1650
        return (char*)param->value;
1651
      }
1652
      if (param->value2 && !strcmp(str, (char*)param->value2)) {
1653
        return (char*)param->value2;
1654
      }
1655
    }
1656
  }
1657
1658
  return NULL;
1659
}
1660
1661
/* DOCDOC */
1662
static int
1663
prot_strings_helper(strmap_t *locations,
1664
                    char **pr_mem_next_p,
1665
                    size_t *pr_mem_left_p,
1666
                    char **value_p)
1667
{
1668
  char *param_val;
1669
  size_t param_size;
1670
  void *location;
1671
1672
  if (*value_p == 0)
1673
    return 0;
1674
1675
  param_val = (char*) *value_p;
1676
  param_size = strlen(param_val) + 1;
1677
  location = strmap_get(locations, param_val);
1678
1679
  if (location) {
1680
    // We already interned this string.
1681
    tor_free(param_val);
1682
    *value_p = location;
1683
    return 0;
1684
  } else if (*pr_mem_left_p >= param_size) {
1685
    // copy to protected
1686
    location = *pr_mem_next_p;
1687
    memcpy(location, param_val, param_size);
1688
1689
    // re-point el parameter to protected
1690
    tor_free(param_val);
1691
    *value_p = location;
1692
1693
    strmap_set(locations, location, location); /* good real estate advice */
1694
1695
    // move next available protected memory
1696
    *pr_mem_next_p += param_size;
1697
    *pr_mem_left_p -= param_size;
1698
    return 0;
1699
  } else {
1700
    log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
1701
    return -1;
1702
  }
1703
}
1704
1705
/**
1706
 * Protects all the strings in the sandbox's parameter list configuration. It
1707
 * works by calculating the total amount of memory required by the parameter
1708
 * list, allocating the memory using mmap, and protecting it from writes with
1709
 * mprotect().
1710
 */
1711
static int
1712
prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
1713
{
1714
  int ret = 0;
1715
  size_t pr_mem_size = 0, pr_mem_left = 0;
1716
  char *pr_mem_next = NULL, *pr_mem_base;
1717
  sandbox_cfg_t *el = NULL;
1718
  strmap_t *locations = NULL;
1719
1720
  // get total number of bytes required to mmap. (Overestimate.)
1721
  for (el = cfg; el != NULL; el = el->next) {
1722
    pr_mem_size += strlen((char*) el->param->value) + 1;
1723
    if (el->param->value2)
1724
      pr_mem_size += strlen((char*) el->param->value2) + 1;
1725
  }
1726
1727
  // allocate protected memory with MALLOC_MP_LIM canary
1728
  pr_mem_base = (char*) mmap(NULL, MALLOC_MP_LIM + pr_mem_size,
1729
      PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1730
  if (pr_mem_base == MAP_FAILED) {
1731
    log_err(LD_BUG,"(Sandbox) failed allocate protected memory! mmap: %s",
1732
        strerror(errno));
1733
    ret = -1;
1734
    goto out;
1735
  }
1736
1737
  pr_mem_next = pr_mem_base + MALLOC_MP_LIM;
1738
  pr_mem_left = pr_mem_size;
1739
1740
  locations = strmap_new();
1741
1742
  // change el value pointer to protected
1743
  for (el = cfg; el != NULL; el = el->next) {
1744
    if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1745
                            &el->param->value) < 0) {
1746
      ret = -2;
1747
      goto out;
1748
    }
1749
    if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
1750
                            &el->param->value2) < 0) {
1751
      ret = -2;
1752
      goto out;
1753
    }
1754
    el->param->prot = 1;
1755
  }
1756
1757
  // protecting from writes
1758
  if (mprotect(pr_mem_base, MALLOC_MP_LIM + pr_mem_size, PROT_READ)) {
1759
    log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s",
1760
        strerror(errno));
1761
    ret = -3;
1762
    goto out;
1763
  }
1764
1765
  /*
1766
   * Setting sandbox restrictions so the string memory cannot be tampered with
1767
   */
1768
  // no mremap of the protected base address
1769
  ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap),
1770
      SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1771
  if (ret) {
1772
    log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!");
1773
    goto out;
1774
  }
1775
1776
  // no munmap of the protected base address
1777
  ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap),
1778
        SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base));
1779
  if (ret) {
1780
    log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!");
1781
    goto out;
1782
  }
1783
1784
  /*
1785
   * Allow mprotect with PROT_READ|PROT_WRITE because openssl uses it, but
1786
   * never over the memory region used by the protected strings.
1787
   *
1788
   * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but
1789
   * had to be removed due to limitation of libseccomp regarding intervals.
1790
   *
1791
   * There is a restriction on how much you can mprotect with R|W up to the
1792
   * size of the canary.
1793
   */
1794
  ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1795
      SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base),
1796
      SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
1797
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1798
  if (ret) {
1799
    log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!");
1800
    goto out;
1801
  }
1802
1803
  ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
1804
      SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size +
1805
          MALLOC_MP_LIM),
1806
      SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
1807
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
1808
  if (ret) {
1809
    log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!");
1810
    goto out;
1811
  }
1812
1813
 out:
1814
  strmap_free(locations, NULL);
1815
  return ret;
1816
}
1817
1818
/**
1819
 * Auxiliary function used in order to allocate a sandbox_cfg_t element and set
1820
 * its values according the parameter list. All elements are initialised
1821
 * with the 'prot' field set to false, as the pointer is not protected at this
1822
 * point.
1823
 */
1824
static sandbox_cfg_t*
1825
new_element2(int syscall, char *value, char *value2)
1826
{
1827
  smp_param_t *param = NULL;
1828
1829
  sandbox_cfg_t *elem = tor_malloc_zero(sizeof(sandbox_cfg_t));
1830
  param = elem->param = tor_malloc_zero(sizeof(smp_param_t));
1831
1832
  param->syscall = syscall;
1833
  param->value = value;
1834
  param->value2 = value2;
1835
  param->prot = 0;
1836
1837
  return elem;
1838
}
1839
1840
static sandbox_cfg_t*
1841
new_element(int syscall, char *value)
1842
{
1843
  return new_element2(syscall, value, NULL);
1844
}
1845
1846
#if defined(ARCH_USES_GENERIC_SYSCALLS)
1847
#define SCMP_chown SCMP_SYS(fchownat)
1848
#elif defined(__i386__)
1849
#define SCMP_chown SCMP_SYS(chown32)
1850
#else
1851
#define SCMP_chown SCMP_SYS(chown)
1852
#endif
1853
1854
#if defined(ARCH_USES_GENERIC_SYSCALLS)
1855
#define SCMP_chmod SCMP_SYS(fchmodat)
1856
#else
1857
#define SCMP_chmod SCMP_SYS(chmod)
1858
#endif
1859
1860
#if defined(__NR_rename)
1861
#define SCMP_rename SCMP_SYS(rename)
1862
#elif defined(__NR_renameat)
1863
#define SCMP_rename SCMP_SYS(renameat)
1864
#else
1865
#define SCMP_rename SCMP_SYS(renameat2)
1866
#endif
1867
1868
#if defined(ARCH_USES_GENERIC_SYSCALLS)
1869
#define SCMP_stat SCMP_SYS(newfstatat)
1870
#elif defined(__NR_stat64)
1871
#define SCMP_stat SCMP_SYS(stat64)
1872
#else
1873
#define SCMP_stat SCMP_SYS(stat)
1874
#endif
1875
1876
int
1877
sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
1878
{
1879
  sandbox_cfg_t *elem = NULL;
1880
1881
  elem = new_element(SCMP_stat, file);
1882
1883
  elem->next = *cfg;
1884
  *cfg = elem;
1885
1886
  return 0;
1887
}
1888
1889
int
1890
sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
1891
{
1892
  sandbox_cfg_t *elem = NULL;
1893
1894
  elem = new_element(SCMP_SYS(open), file);
1895
1896
  elem->next = *cfg;
1897
  *cfg = elem;
1898
1899
  return 0;
1900
}
1901
1902
int
1903
sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file)
1904
{
1905
  sandbox_cfg_t *elem = NULL;
1906
1907
  elem = new_element(SCMP_chmod, file);
1908
1909
  elem->next = *cfg;
1910
  *cfg = elem;
1911
1912
  return 0;
1913
}
1914
1915
int
1916
sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
1917
{
1918
  sandbox_cfg_t *elem = NULL;
1919
1920
  elem = new_element(SCMP_chown, file);
1921
1922
  elem->next = *cfg;
1923
  *cfg = elem;
1924
1925
  return 0;
1926
}
1927
1928
int
1929
sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
1930
{
1931
  sandbox_cfg_t *elem = NULL;
1932
1933
  elem = new_element2(SCMP_rename, file1, file2);
1934
1935
  elem->next = *cfg;
1936
  *cfg = elem;
1937
1938
  return 0;
1939
}
1940
1941
int
1942
sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
1943
{
1944
  sandbox_cfg_t *elem = NULL;
1945
1946
  elem = new_element(SCMP_SYS(openat), file);
1947
1948
  elem->next = *cfg;
1949
  *cfg = elem;
1950
1951
  return 0;
1952
}
1953
1954
int
1955
sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir)
1956
{
1957
  sandbox_cfg_t *elem = NULL;
1958
1959
  elem = new_element(PHONY_OPENDIR_SYSCALL, dir);
1960
1961
  elem->next = *cfg;
1962
  *cfg = elem;
1963
1964
  return 0;
1965
}
1966
1967
/**
1968
 * Function responsible for going through the parameter syscall filters and
1969
 * call each function pointer in the list.
1970
 */
1971
static int
1972
add_param_filter(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
1973
{
1974
  unsigned i;
1975
  int rc = 0;
1976
1977
  // function pointer
1978
  for (i = 0; i < ARRAY_LENGTH(filter_func); i++) {
1979
    rc = filter_func[i](ctx, cfg);
1980
    if (rc) {
1981
      log_err(LD_BUG,"(Sandbox) failed to add syscall %d, received libseccomp "
1982
          "error %d", i, rc);
1983
      return rc;
1984
    }
1985
  }
1986
1987
  return 0;
1988
}
1989
1990
/**
1991
 * Function responsible of loading the libseccomp syscall filters which do not
1992
 * have parameter filtering.
1993
 */
1994
static int
1995
add_noparam_filter(scmp_filter_ctx ctx)
1996
{
1997
  unsigned i;
1998
  int rc = 0;
1999
2000
  // add general filters
2001
  for (i = 0; i < ARRAY_LENGTH(filter_nopar_gen); i++) {
2002
    rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, filter_nopar_gen[i]);
2003
    if (rc != 0) {
2004
      log_err(LD_BUG,"(Sandbox) failed to add syscall index %d (NR=%d), "
2005
          "received libseccomp error %d", i, filter_nopar_gen[i], rc);
2006
      return rc;
2007
    }
2008
  }
2009
2010
  if (is_libc_at_least(2, 33)) {
2011
#ifdef __NR_newfstatat
2012
    // Libc 2.33 uses this syscall to implement both fstat() and stat().
2013
    //
2014
    // The trouble is that to implement fstat(fd, &st), it calls:
2015
    //     newfstatat(fs, "", &st, AT_EMPTY_PATH)
2016
    // We can't detect this usage in particular, because "" is a pointer
2017
    // we don't control.  And we can't just look for AT_EMPTY_PATH, since
2018
    // AT_EMPTY_PATH only has effect when the path string is empty.
2019
    //
2020
    // So our only solution seems to be allowing all fstatat calls, which
2021
    // means that an attacker can stat() anything on the filesystem. That's
2022
    // not a great solution, but I can't find a better one.
2023
    rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(newfstatat));
2024
    if (rc != 0) {
2025
      log_err(LD_BUG,"(Sandbox) failed to add newfstatat() syscall; "
2026
          "received libseccomp error %d", rc);
2027
      return rc;
2028
    }
2029
#elif defined(__NR_fstatat64)
2030
    // On i386, glibc uses fstatat64 instead of newfstatat.
2031
    // This is needed for glob() and stat() operations on 32-bit systems.
2032
    rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fstatat64));
2033
    if (rc != 0) {
2034
      log_err(LD_BUG,"(Sandbox) failed to add fstatat64() syscall; "
2035
          "received libseccomp error %d", rc);
2036
      return rc;
2037
    }
2038
#endif
2039
#if defined(__i386__) && defined(__NR_statx)
2040
    // On i386 with glibc 2.33+, statx may be used for time64 support.
2041
    // glob() in glibc 2.36+ uses statx for directory traversal.
2042
    rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(statx));
2043
    if (rc != 0) {
2044
      log_err(LD_BUG,"(Sandbox) failed to add statx() syscall; "
2045
          "received libseccomp error %d", rc);
2046
      return rc;
2047
    }
2048
#endif
2049
  }
2050
2051
  return 0;
2052
}
2053
2054
/**
2055
 * Function responsible for setting up and enabling a global syscall filter.
2056
 * The function is a prototype developed for stage 1 of sandboxing Tor.
2057
 * Returns 0 on success.
2058
 */
2059
static int
2060
install_syscall_filter(sandbox_cfg_t* cfg)
2061
{
2062
  int rc = 0;
2063
  scmp_filter_ctx ctx;
2064
2065
  ctx = seccomp_init(SCMP_ACT_ERRNO(EPERM));
2066
  if (ctx == NULL) {
2067
    log_err(LD_BUG,"(Sandbox) failed to initialise libseccomp context");
2068
    rc = -1;
2069
    goto end;
2070
  }
2071
2072
  // protecting sandbox parameter strings
2073
  if ((rc = prot_strings(ctx, cfg))) {
2074
    goto end;
2075
  }
2076
2077
  // add parameter filters
2078
  if ((rc = add_param_filter(ctx, cfg))) {
2079
    log_err(LD_BUG, "(Sandbox) failed to add param filters!");
2080
    goto end;
2081
  }
2082
2083
  // adding filters with no parameters
2084
  if ((rc = add_noparam_filter(ctx))) {
2085
    log_err(LD_BUG, "(Sandbox) failed to add param filters!");
2086
    goto end;
2087
  }
2088
2089
  // loading the seccomp2 filter
2090
  if ((rc = seccomp_load(ctx))) {
2091
    log_err(LD_BUG, "(Sandbox) failed to load: %d (%s)! "
2092
            "Are you sure that your kernel has seccomp2 support? The "
2093
            "sandbox won't work without it.", rc,
2094
            strerror(-rc));
2095
    goto end;
2096
  }
2097
2098
  // marking the sandbox as active
2099
  sandbox_active = 1;
2100
2101
 end:
2102
  seccomp_release(ctx);
2103
  return (rc < 0 ? -rc : rc);
2104
}
2105
2106
#ifdef SYSCALL_NAME_DEBUGGING
2107
#include "lib/sandbox/linux_syscalls.inc"
2108
2109
/** Return a string containing the name of a given syscall (if we know it) */
2110
static const char *
2111
get_syscall_name(int syscall_num)
2112
{
2113
  int i;
2114
  for (i = 0; SYSCALLS_BY_NUMBER[i].syscall_name; ++i) {
2115
    if (SYSCALLS_BY_NUMBER[i].syscall_num == syscall_num)
2116
      return SYSCALLS_BY_NUMBER[i].syscall_name;
2117
  }
2118
2119
  {
2120
     static char syscall_name_buf[64];
2121
     format_dec_number_sigsafe(syscall_num,
2122
                               syscall_name_buf, sizeof(syscall_name_buf));
2123
     return syscall_name_buf;
2124
  }
2125
}
2126
2127
/** Return the syscall number from a ucontext_t that we got in a signal
2128
 * handler (if we know how to do that). */
2129
static int
2130
get_syscall_from_ucontext(const ucontext_t *ctx)
2131
{
2132
  return (int) ctx->uc_mcontext.M_SYSCALL;
2133
}
2134
#else /* !defined(SYSCALL_NAME_DEBUGGING) */
2135
static const char *
2136
get_syscall_name(int syscall_num)
2137
{
2138
  (void) syscall_num;
2139
  return "unknown";
2140
}
2141
static int
2142
get_syscall_from_ucontext(const ucontext_t *ctx)
2143
{
2144
  (void) ctx;
2145
  return -1;
2146
}
2147
#endif /* defined(SYSCALL_NAME_DEBUGGING) */
2148
2149
#ifdef USE_BACKTRACE
2150
#define MAX_DEPTH 256
2151
static void *syscall_cb_buf[MAX_DEPTH];
2152
#endif
2153
2154
/**
2155
 * Function called when a SIGSYS is caught by the application. It notifies the
2156
 * user that an error has occurred and either terminates or allows the
2157
 * application to continue execution, based on the DEBUGGING_CLOSE symbol.
2158
 */
2159
static void
2160
sigsys_debugging(int nr, siginfo_t *info, void *void_context)
2161
{
2162
  ucontext_t *ctx = (ucontext_t *) (void_context);
2163
  const char *syscall_name;
2164
#ifdef USE_BACKTRACE
2165
  size_t depth;
2166
  int n_fds, i;
2167
  const int *fds = NULL;
2168
#endif
2169
2170
  (void) nr;
2171
2172
  if (info->si_code != SYS_SECCOMP)
2173
    return;
2174
2175
  if (!ctx)
2176
    return;
2177
2178
  int syscall = get_syscall_from_ucontext(ctx);
2179
2180
#ifdef USE_BACKTRACE
2181
  depth = backtrace(syscall_cb_buf, MAX_DEPTH);
2182
  /* Clean up the top stack frame so we get the real function
2183
   * name for the most recently failing function. */
2184
  clean_backtrace(syscall_cb_buf, depth, ctx);
2185
#endif /* defined(USE_BACKTRACE) */
2186
2187
  syscall_name = get_syscall_name(syscall);
2188
2189
  tor_log_err_sigsafe("(Sandbox) Caught a bad syscall attempt (syscall ",
2190
                      syscall_name,
2191
                      ")\n",
2192
                      NULL);
2193
2194
#ifdef USE_BACKTRACE
2195
  n_fds = tor_log_get_sigsafe_err_fds(&fds);
2196
  for (i=0; i < n_fds; ++i)
2197
    backtrace_symbols_fd(syscall_cb_buf, (int)depth, fds[i]);
2198
#endif
2199
2200
#if defined(DEBUGGING_CLOSE)
2201
  _exit(1); // exit ok: programming error has led to sandbox failure.
2202
#endif // DEBUGGING_CLOSE
2203
}
2204
2205
/**
2206
 * Function that adds a handler for SIGSYS, which is the signal thrown
2207
 * when the application is issuing a syscall which is not allowed. The
2208
 * main purpose of this function is to help with debugging by identifying
2209
 * filtered syscalls.
2210
 */
2211
static int
2212
install_sigsys_debugging(void)
2213
{
2214
  struct sigaction act;
2215
  sigset_t mask;
2216
2217
  memset(&act, 0, sizeof(act));
2218
  sigemptyset(&mask);
2219
  sigaddset(&mask, SIGSYS);
2220
2221
  act.sa_sigaction = &sigsys_debugging;
2222
  act.sa_flags = SA_SIGINFO;
2223
  if (sigaction(SIGSYS, &act, NULL) < 0) {
2224
    log_err(LD_BUG,"(Sandbox) Failed to register SIGSYS signal handler");
2225
    return -1;
2226
  }
2227
2228
  if (sigprocmask(SIG_UNBLOCK, &mask, NULL)) {
2229
    log_err(LD_BUG,"(Sandbox) Failed call to sigprocmask()");
2230
    return -2;
2231
  }
2232
2233
  return 0;
2234
}
2235
2236
/**
2237
 * Function responsible of registering the sandbox_cfg_t list of parameter
2238
 * syscall filters to the existing parameter list. This is used for incipient
2239
 * multiple-sandbox support.
2240
 */
2241
static int
2242
register_cfg(sandbox_cfg_t* cfg)
2243
{
2244
  sandbox_cfg_t *elem = NULL;
2245
2246
  if (filter_dynamic == NULL) {
2247
    filter_dynamic = cfg;
2248
    return 0;
2249
  }
2250
2251
  for (elem = filter_dynamic; elem->next != NULL; elem = elem->next)
2252
    ;
2253
2254
  elem->next = cfg;
2255
2256
  return 0;
2257
}
2258
2259
#endif /* defined(USE_LIBSECCOMP) */
2260
2261
#ifdef USE_LIBSECCOMP
2262
/**
2263
 * Initialises the syscall sandbox filter for any linux architecture, taking
2264
 * into account various available features for different linux flavours.
2265
 */
2266
static int
2267
initialise_libseccomp_sandbox(sandbox_cfg_t* cfg)
2268
{
2269
  /* Prevent glibc from trying to open /dev/tty on fatal error */
2270
  setenv("LIBC_FATAL_STDERR_", "1", 1);
2271
2272
  if (install_sigsys_debugging())
2273
    return -1;
2274
2275
  if (install_syscall_filter(cfg))
2276
    return -2;
2277
2278
  if (register_cfg(cfg))
2279
    return -3;
2280
2281
  return 0;
2282
}
2283
2284
int
2285
sandbox_is_active(void)
2286
{
2287
  return sandbox_active != 0;
2288
}
2289
#endif /* defined(USE_LIBSECCOMP) */
2290
2291
sandbox_cfg_t*
2292
sandbox_cfg_new(void)
2293
0
{
2294
0
  return NULL;
2295
0
}
2296
2297
int
2298
sandbox_init(sandbox_cfg_t *cfg)
2299
0
{
2300
#if defined(USE_LIBSECCOMP)
2301
  return initialise_libseccomp_sandbox(cfg);
2302
2303
#elif defined(__linux__)
2304
  (void)cfg;
2305
0
  log_warn(LD_GENERAL,
2306
0
           "This version of Tor was built without support for sandboxing. To "
2307
0
           "build with support for sandboxing on Linux, you must have "
2308
0
           "libseccomp and its necessary header files (e.g. seccomp.h).");
2309
0
  return 0;
2310
2311
#else
2312
  (void)cfg;
2313
  log_warn(LD_GENERAL,
2314
           "Currently, sandboxing is only implemented on Linux. The feature "
2315
           "is disabled on your platform.");
2316
  return 0;
2317
#endif /* defined(USE_LIBSECCOMP) || ... */
2318
0
}
2319
2320
#ifndef USE_LIBSECCOMP
2321
int
2322
sandbox_cfg_allow_open_filename(sandbox_cfg_t **cfg, char *file)
2323
0
{
2324
0
  (void)cfg; (void)file;
2325
0
  return 0;
2326
0
}
2327
2328
int
2329
sandbox_cfg_allow_openat_filename(sandbox_cfg_t **cfg, char *file)
2330
0
{
2331
0
  (void)cfg; (void)file;
2332
0
  return 0;
2333
0
}
2334
2335
int
2336
sandbox_cfg_allow_opendir_dirname(sandbox_cfg_t **cfg, char *dir)
2337
0
{
2338
0
  (void)cfg; (void)dir;
2339
0
  return 0;
2340
0
}
2341
2342
int
2343
sandbox_cfg_allow_stat_filename(sandbox_cfg_t **cfg, char *file)
2344
0
{
2345
0
  (void)cfg; (void)file;
2346
0
  return 0;
2347
0
}
2348
2349
int
2350
sandbox_cfg_allow_chown_filename(sandbox_cfg_t **cfg, char *file)
2351
0
{
2352
0
  (void)cfg; (void)file;
2353
0
  return 0;
2354
0
}
2355
2356
int
2357
sandbox_cfg_allow_chmod_filename(sandbox_cfg_t **cfg, char *file)
2358
0
{
2359
0
  (void)cfg; (void)file;
2360
0
  return 0;
2361
0
}
2362
2363
int
2364
sandbox_cfg_allow_rename(sandbox_cfg_t **cfg, char *file1, char *file2)
2365
0
{
2366
0
  (void)cfg; (void)file1; (void)file2;
2367
0
  return 0;
2368
0
}
2369
2370
int
2371
sandbox_is_active(void)
2372
0
{
2373
0
  return 0;
2374
0
}
2375
2376
#endif /* !defined(USE_LIBSECCOMP) */