sandbox.c 42.2 KB
Newer Older
1
/* Copyright (c) 2001 Matej Pfajfar.
2
3
 * Copyright (c) 2001-2004, Roger Dingledine.
 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
Nick Mathewson's avatar
Nick Mathewson committed
4
 * Copyright (c) 2007-2019, The Tor Project, Inc. */
5
6
7
8
9
10
11
/* See LICENSE for licensing information */

/**
 * \file sandbox.c
 * \brief Code to enable sandboxing.
 **/

12
13
14
#include "orconfig.h"

#ifndef _LARGEFILE64_SOURCE
Cristian Toader's avatar
Cristian Toader committed
15
16
17
18
/**
 * Temporarily required for O_LARGEFILE flag. Needs to be removed
 * with the libevent fix.
 */
Cristian Toader's avatar
Cristian Toader committed
19
#define _LARGEFILE64_SOURCE
20
#endif /* !defined(_LARGEFILE64_SOURCE) */
Cristian Toader's avatar
Cristian Toader committed
21

22
23
24
25
26
27
28
29
/** Malloc mprotect limit in bytes.
 *
 * 28/06/2017: This value was increased from 16 MB to 20 MB after we introduced
 * LZMA support in Tor (0.3.1.1-alpha). We limit our LZMA coder to 16 MB, but
 * liblzma have a small overhead that we need to compensate for to avoid being
 * killed by the sandbox.
 */
#define MALLOC_MP_LIM (20*1024*1024)
30

31
32
33
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
34
#include <errno.h>
35

36
#include "lib/sandbox/sandbox.h"
Nick Mathewson's avatar
Nick Mathewson committed
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/net/resolve.h"
Nick Mathewson's avatar
Nick Mathewson committed
42
#include "lib/malloc/malloc.h"
43
#include "lib/string/scanf.h"
44

45
#include "tor_queue.h"
46
#include "ht.h"
Nick Mathewson's avatar
Nick Mathewson committed
47
48
#include "siphash.h"

49
50
51
52
#define DEBUGGING_CLOSE

#if defined(USE_LIBSECCOMP)

53
#include <sys/mman.h>
54
#include <sys/syscall.h>
55
#include <sys/types.h>
Cristian Toader's avatar
Cristian Toader committed
56
#include <sys/stat.h>
Cristian Toader's avatar
Cristian Toader committed
57
#include <sys/epoll.h>
58
59
#include <sys/prctl.h>
#include <linux/futex.h>
60
#include <sys/file.h>
61

62
#include <stdarg.h>
63
64
65
#include <seccomp.h>
#include <signal.h>
#include <unistd.h>
66
#include <fcntl.h>
67
#include <time.h>
68
#include <poll.h>
69

70
71
72
#ifdef HAVE_GNU_LIBC_VERSION_H
#include <gnu/libc-version.h>
#endif
73
74
75
76
77
78
79
80
81
82
#ifdef HAVE_LINUX_NETFILTER_IPV4_H
#include <linux/netfilter_ipv4.h>
#endif
#ifdef HAVE_LINUX_IF_H
#include <linux/if.h>
#endif
#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
#include <linux/netfilter_ipv6/ip6_tables.h>
#endif

83
84
85
86
#if defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && \
  defined(HAVE_BACKTRACE_SYMBOLS_FD) && defined(HAVE_SIGACTION)
#define USE_BACKTRACE
#define EXPOSE_CLEAN_BACKTRACE
87
#include "lib/err/backtrace.h"
88
#endif /* defined(HAVE_EXECINFO_H) && defined(HAVE_BACKTRACE) && ... */
89
90
91
92
93

#ifdef USE_BACKTRACE
#include <execinfo.h>
#endif

Nick Mathewson's avatar
Nick Mathewson committed
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/**
 * Linux 32 bit definitions
 */
#if defined(__i386__)

#define REG_SYSCALL REG_EAX
#define M_SYSCALL gregs[REG_SYSCALL]

/**
 * Linux 64 bit definitions
 */
#elif defined(__x86_64__)

#define REG_SYSCALL REG_RAX
#define M_SYSCALL gregs[REG_SYSCALL]

#elif defined(__arm__)

#define M_SYSCALL arm_r7

114
115
116
117
118
#elif defined(__aarch64__) && defined(__LP64__)

#define REG_SYSCALL 8
#define M_SYSCALL regs[REG_SYSCALL]

119
#endif /* defined(__i386__) || ... */
Nick Mathewson's avatar
Nick Mathewson committed
120

121
/**Determines if at least one sandbox is active.*/
122
static int sandbox_active = 0;
123
/** Holds the parameter list configuration for the sandbox.*/
Cristian Toader's avatar
Cristian Toader committed
124
static sandbox_cfg_t *filter_dynamic = NULL;
125

126
127
#undef SCMP_CMP
#define SCMP_CMP(a,b,c) ((struct scmp_arg_cmp){(a),(b),(c),0})
128
#define SCMP_CMP_STR(a,b,c) \
Nick Mathewson's avatar
Nick Mathewson committed
129
  ((struct scmp_arg_cmp) {(a),(b),(intptr_t)(void*)(c),0})
130
131
132
133
134
135
136
#define SCMP_CMP4(a,b,c,d) ((struct scmp_arg_cmp){(a),(b),(c),(d)})
/* We use a wrapper here because these masked comparisons seem to be pretty
 * verbose. Also, it's important to cast to scmp_datum_t before negating the
 * mask, since otherwise the negation might get applied to a 32 bit value, and
 * the high bits of the value might get masked out improperly. */
#define SCMP_CMP_MASKED(a,b,c) \
  SCMP_CMP4((a), SCMP_CMP_MASKED_EQ, ~(scmp_datum_t)(b), (c))
137

138
139
140
/** Variable used for storing all syscall numbers that will be allowed with the
 * stage 1 general Tor sandbox.
 */
141
static int filter_nopar_gen[] = {
142
    SCMP_SYS(access),
143
    SCMP_SYS(brk),
Cristian Toader's avatar
Cristian Toader committed
144
    SCMP_SYS(clock_gettime),
145
146
147
148
    SCMP_SYS(close),
    SCMP_SYS(clone),
    SCMP_SYS(epoll_create),
    SCMP_SYS(epoll_wait),
149
150
151
#ifdef __NR_epoll_pwait
    SCMP_SYS(epoll_pwait),
#endif
Nick Mathewson's avatar
Nick Mathewson committed
152
#ifdef HAVE_EVENTFD
153
    SCMP_SYS(eventfd2),
Nick Mathewson's avatar
Nick Mathewson committed
154
155
156
157
158
159
#endif
#ifdef HAVE_PIPE2
    SCMP_SYS(pipe2),
#endif
#ifdef HAVE_PIPE
    SCMP_SYS(pipe),
160
161
162
#endif
#ifdef __NR_fchmod
    SCMP_SYS(fchmod),
Nick Mathewson's avatar
Nick Mathewson committed
163
#endif
164
165
166
167
168
    SCMP_SYS(fcntl),
    SCMP_SYS(fstat),
#ifdef __NR_fstat64
    SCMP_SYS(fstat64),
#endif
169
    SCMP_SYS(futex),
170
    SCMP_SYS(getdents),
171
172
173
174
175
176
177
178
179
180
181
182
183
    SCMP_SYS(getdents64),
    SCMP_SYS(getegid),
#ifdef __NR_getegid32
    SCMP_SYS(getegid32),
#endif
    SCMP_SYS(geteuid),
#ifdef __NR_geteuid32
    SCMP_SYS(geteuid32),
#endif
    SCMP_SYS(getgid),
#ifdef __NR_getgid32
    SCMP_SYS(getgid32),
#endif
184
    SCMP_SYS(getpid),
Nick Mathewson's avatar
Nick Mathewson committed
185
#ifdef __NR_getrlimit
186
    SCMP_SYS(getrlimit),
Nick Mathewson's avatar
Nick Mathewson committed
187
#endif
188
    SCMP_SYS(gettimeofday),
189
    SCMP_SYS(gettid),
190
191
192
193
194
195
196
197
198
199
    SCMP_SYS(getuid),
#ifdef __NR_getuid32
    SCMP_SYS(getuid32),
#endif
    SCMP_SYS(lseek),
#ifdef __NR__llseek
    SCMP_SYS(_llseek),
#endif
    SCMP_SYS(mkdir),
    SCMP_SYS(mlockall),
Nick Mathewson's avatar
Nick Mathewson committed
200
201
#ifdef __NR_mmap
    /* XXXX restrict this in the same ways as mmap2 */
202
    SCMP_SYS(mmap),
Nick Mathewson's avatar
Nick Mathewson committed
203
#endif
204
    SCMP_SYS(munmap),
205
206
207
#ifdef __NR_nanosleep
    SCMP_SYS(nanosleep),
#endif
208
209
210
211
212
213
#ifdef __NR_prlimit
    SCMP_SYS(prlimit),
#endif
#ifdef __NR_prlimit64
    SCMP_SYS(prlimit64),
#endif
214
215
    SCMP_SYS(read),
    SCMP_SYS(rt_sigreturn),
216
    SCMP_SYS(sched_getaffinity),
217
218
219
#ifdef __NR_sched_yield
    SCMP_SYS(sched_yield),
#endif
220
    SCMP_SYS(sendmsg),
221
    SCMP_SYS(set_robust_list),
222
223
224
#ifdef __NR_setrlimit
    SCMP_SYS(setrlimit),
#endif
225
    SCMP_SYS(shutdown),
226
227
228
#ifdef __NR_sigaltstack
    SCMP_SYS(sigaltstack),
#endif
229
230
231
232
#ifdef __NR_sigreturn
    SCMP_SYS(sigreturn),
#endif
    SCMP_SYS(stat),
233
    SCMP_SYS(uname),
234
    SCMP_SYS(wait4),
235
    SCMP_SYS(write),
236
    SCMP_SYS(writev),
237
238
239
    SCMP_SYS(exit_group),
    SCMP_SYS(exit),

240
    SCMP_SYS(madvise),
Nick Mathewson's avatar
Nick Mathewson committed
241
#ifdef __NR_stat64
242
243
    // getaddrinfo uses this..
    SCMP_SYS(stat64),
Nick Mathewson's avatar
Nick Mathewson committed
244
#endif
245

246
247
248
249
#ifdef __NR_getrandom
    SCMP_SYS(getrandom),
#endif

250
251
252
253
#ifdef __NR_sysinfo
    // qsort uses this..
    SCMP_SYS(sysinfo),
#endif
254
255
256
257
258
259
260
261
262
    /*
     * These socket syscalls are not required on x86_64 and not supported with
     * some libseccomp versions (eg: 1.0.1)
     */
#if defined(__i386)
    SCMP_SYS(recv),
    SCMP_SYS(send),
#endif

263
264
    // socket syscalls
    SCMP_SYS(bind),
Nick Mathewson's avatar
Nick Mathewson committed
265
    SCMP_SYS(listen),
266
267
    SCMP_SYS(connect),
    SCMP_SYS(getsockname),
268
269
270
271
272
#ifdef ENABLE_NSS
#ifdef __NR_getpeername
    SCMP_SYS(getpeername),
#endif
#endif
273
    SCMP_SYS(recvmsg),
Cristian Toader's avatar
Cristian Toader committed
274
    SCMP_SYS(recvfrom),
275
    SCMP_SYS(sendto),
276
277
    SCMP_SYS(unlink),
    SCMP_SYS(poll)
278
279
};

280
281
282
283
284
285
286
287
288
289
290
291
292
/* These macros help avoid the error where the number of filters we add on a
 * single rule don't match the arg_cnt param. */
#define seccomp_rule_add_0(ctx,act,call) \
  seccomp_rule_add((ctx),(act),(call),0)
#define seccomp_rule_add_1(ctx,act,call,f1) \
  seccomp_rule_add((ctx),(act),(call),1,(f1))
#define seccomp_rule_add_2(ctx,act,call,f1,f2)  \
  seccomp_rule_add((ctx),(act),(call),2,(f1),(f2))
#define seccomp_rule_add_3(ctx,act,call,f1,f2,f3)       \
  seccomp_rule_add((ctx),(act),(call),3,(f1),(f2),(f3))
#define seccomp_rule_add_4(ctx,act,call,f1,f2,f3,f4)      \
  seccomp_rule_add((ctx),(act),(call),4,(f1),(f2),(f3),(f4))

293
294
295
296
/**
 * Function responsible for setting up the rt_sigaction syscall for
 * the seccomp filter sandbox.
 */
297
static int
298
sb_rt_sigaction(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
299
{
300
301
  unsigned i;
  int rc;
302
303
304
305
306
  int param[] = { SIGINT, SIGTERM, SIGPIPE, SIGUSR1, SIGUSR2, SIGHUP, SIGCHLD,
#ifdef SIGXFSZ
      SIGXFSZ
#endif
      };
307
  (void) filter;
308

Cristian Toader's avatar
Cristian Toader committed
309
  for (i = 0; i < ARRAY_LENGTH(param); i++) {
310
    rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigaction),
311
        SCMP_CMP(0, SCMP_CMP_EQ, param[i]));
Cristian Toader's avatar
Cristian Toader committed
312
    if (rc)
313
314
315
316
317
318
      break;
  }

  return rc;
}

319
320
321
322
/**
 * Function responsible for setting up the time syscall for
 * the seccomp filter sandbox.
 */
323
static int
324
sb_time(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
325
{
326
  (void) filter;
Nick Mathewson's avatar
Nick Mathewson committed
327
#ifdef __NR_time
328
  return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(time),
329
       SCMP_CMP(0, SCMP_CMP_EQ, 0));
Nick Mathewson's avatar
Nick Mathewson committed
330
331
#else
  return 0;
332
#endif /* defined(__NR_time) */
333
334
}

335
336
337
338
/**
 * Function responsible for setting up the accept4 syscall for
 * the seccomp filter sandbox.
 */
339
static int
340
sb_accept4(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
341
{
Cristian Toader's avatar
Cristian Toader committed
342
  int rc = 0;
343
  (void)filter;
Cristian Toader's avatar
Cristian Toader committed
344
345

#ifdef __i386__
346
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketcall),
Cristian Toader's avatar
Cristian Toader committed
347
      SCMP_CMP(0, SCMP_CMP_EQ, 18));
Cristian Toader's avatar
Cristian Toader committed
348
349
350
  if (rc) {
    return rc;
  }
351
#endif /* defined(__i386__) */
Cristian Toader's avatar
Cristian Toader committed
352

353
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(accept4),
354
                   SCMP_CMP_MASKED(3, SOCK_CLOEXEC|SOCK_NONBLOCK, 0));
355
356
357
  if (rc) {
    return rc;
  }
Cristian Toader's avatar
Cristian Toader committed
358
359

  return 0;
360
361
362
}

#ifdef __NR_mmap2
363
364
365
366
/**
 * Function responsible for setting up the mmap2 syscall for
 * the seccomp filter sandbox.
 */
367
static int
368
sb_mmap2(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
369
{
370
  int rc = 0;
Nick Mathewson's avatar
Nick Mathewson committed
371
  (void)filter;
372

373
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
374
375
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ),
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE));
Cristian Toader's avatar
Cristian Toader committed
376
  if (rc) {
377
    return rc;
378
379
  }

380
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
381
382
383
384
385
386
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE),
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS|MAP_NORESERVE));
  if (rc) {
    return rc;
  }

387
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
388
389
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
       SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_ANONYMOUS));
Cristian Toader's avatar
Cristian Toader committed
390
  if (rc) {
391
392
393
    return rc;
  }

394
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
395
396
397
398
399
400
       SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
       SCMP_CMP(3, SCMP_CMP_EQ,MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK));
  if (rc) {
    return rc;
  }

401
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
402
403
404
405
406
407
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
      SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE));
  if (rc) {
    return rc;
  }

408
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
409
410
411
412
413
414
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE),
      SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS));
  if (rc) {
    return rc;
  }

415
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap2),
416
417
418
419
420
421
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_EXEC),
      SCMP_CMP(3, SCMP_CMP_EQ, MAP_PRIVATE|MAP_DENYWRITE));
  if (rc) {
    return rc;
  }

422
423
  return 0;
}
424
#endif /* defined(__NR_mmap2) */
425

426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
#ifdef HAVE_GNU_LIBC_VERSION_H
#ifdef HAVE_GNU_GET_LIBC_VERSION
#define CHECK_LIBC_VERSION
#endif
#endif

/* Return true if we think we're running with a libc that always uses
 * openat on linux. */
static int
libc_uses_openat_for_everything(void)
{
#ifdef CHECK_LIBC_VERSION
  const char *version = gnu_get_libc_version();
  if (version == NULL)
    return 0;

  int major = -1;
  int minor = -1;

  tor_sscanf(version, "%d.%d", &major, &minor);
  if (major >= 3)
    return 1;
  else if (major == 2 && minor >= 26)
    return 1;
  else
    return 0;
452
#else /* !(defined(CHECK_LIBC_VERSION)) */
453
  return 0;
454
#endif /* defined(CHECK_LIBC_VERSION) */
455
456
}

457
458
459
460
461
462
463
/** Allow a single file to be opened.  If <b>use_openat</b> is true,
 * we're using a libc that remaps all the opens into openats. */
static int
allow_file_open(scmp_filter_ctx ctx, int use_openat, const char *file)
{
  if (use_openat) {
    return seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
464
                              SCMP_CMP(0, SCMP_CMP_EQ, (unsigned int)AT_FDCWD),
465
466
467
468
469
470
471
                              SCMP_CMP_STR(1, SCMP_CMP_EQ, file));
  } else {
    return seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open),
                              SCMP_CMP_STR(0, SCMP_CMP_EQ, file));
  }
}

472
473
474
475
/**
 * Function responsible for setting up the open syscall for
 * the seccomp filter sandbox.
 */
476
static int
477
sb_open(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
478
{
479
  int rc;
480
  sandbox_cfg_t *elem = NULL;
481

482
483
  int use_openat = libc_uses_openat_for_everything();

484
  // for each dynamic parameter filters
485
  for (elem = filter; elem != NULL; elem = elem->next) {
486
487
488
489
    smp_param_t *param = elem->param;

    if (param != NULL && param->prot == 1 && param->syscall
        == SCMP_SYS(open)) {
490
      rc = allow_file_open(ctx, use_openat, param->value);
491
      if (rc != 0) {
Cristian Toader's avatar
Cristian Toader committed
492
493
        log_err(LD_BUG,"(Sandbox) failed to add open syscall, received "
            "libseccomp error %d", rc);
494
495
        return rc;
      }
496
497
498
    }
  }

499
500
501
  return 0;
}

502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
static int
sb_chmod(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc;
  sandbox_cfg_t *elem = NULL;

  // for each dynamic parameter filters
  for (elem = filter; elem != NULL; elem = elem->next) {
    smp_param_t *param = elem->param;

    if (param != NULL && param->prot == 1 && param->syscall
        == SCMP_SYS(chmod)) {
      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chmod),
            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
      if (rc != 0) {
517
        log_err(LD_BUG,"(Sandbox) failed to add chmod syscall, received "
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
            "libseccomp error %d", rc);
        return rc;
      }
    }
  }

  return 0;
}

static int
sb_chown(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc;
  sandbox_cfg_t *elem = NULL;

  // for each dynamic parameter filters
  for (elem = filter; elem != NULL; elem = elem->next) {
    smp_param_t *param = elem->param;

    if (param != NULL && param->prot == 1 && param->syscall
        == SCMP_SYS(chown)) {
      rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(chown),
            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value));
      if (rc != 0) {
542
        log_err(LD_BUG,"(Sandbox) failed to add chown syscall, received "
543
544
545
546
547
548
549
550
551
            "libseccomp error %d", rc);
        return rc;
      }
    }
  }

  return 0;
}

552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
/**
 * Function responsible for setting up the rename syscall for
 * the seccomp filter sandbox.
 */
static int
sb_rename(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc;
  sandbox_cfg_t *elem = NULL;

  // for each dynamic parameter filters
  for (elem = filter; elem != NULL; elem = elem->next) {
    smp_param_t *param = elem->param;

    if (param != NULL && param->prot == 1 &&
        param->syscall == SCMP_SYS(rename)) {

569
      rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rename),
570
571
            SCMP_CMP_STR(0, SCMP_CMP_EQ, param->value),
            SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value2));
572
573
574
575
576
577
578
579
580
581
582
      if (rc != 0) {
        log_err(LD_BUG,"(Sandbox) failed to add rename syscall, received "
            "libseccomp error %d", rc);
        return rc;
      }
    }
  }

  return 0;
}

583
584
585
586
/**
 * Function responsible for setting up the openat syscall for
 * the seccomp filter sandbox.
 */
587
static int
588
sb_openat(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
589
{
590
  int rc;
591
  sandbox_cfg_t *elem = NULL;
592
593

  // for each dynamic parameter filters
594
  for (elem = filter; elem != NULL; elem = elem->next) {
595
596
597
598
    smp_param_t *param = elem->param;

    if (param != NULL && param->prot == 1 && param->syscall
        == SCMP_SYS(openat)) {
599
      rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat),
Cristian Toader's avatar
Cristian Toader committed
600
          SCMP_CMP(0, SCMP_CMP_EQ, AT_FDCWD),
601
          SCMP_CMP_STR(1, SCMP_CMP_EQ, param->value),
Cristian Toader's avatar
Cristian Toader committed
602
603
          SCMP_CMP(2, SCMP_CMP_EQ, O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|
              O_CLOEXEC));
604
      if (rc != 0) {
605
606
        log_err(LD_BUG,"(Sandbox) failed to add openat syscall, received "
            "libseccomp error %d", rc);
607
608
609
610
611
612
613
614
        return rc;
      }
    }
  }

  return 0;
}

615
616
617
618
/**
 * Function responsible for setting up the socket syscall for
 * the seccomp filter sandbox.
 */
619
static int
620
sb_socket(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
621
622
{
  int rc = 0;
623
  int i, j;
624
  (void) filter;
625

Cristian Toader's avatar
Cristian Toader committed
626
#ifdef __i386__
627
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket));
Cristian Toader's avatar
Cristian Toader committed
628
629
630
631
  if (rc)
    return rc;
#endif

632
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
Cristian Toader's avatar
Cristian Toader committed
633
      SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
634
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM));
Cristian Toader's avatar
Cristian Toader committed
635
636
637
  if (rc)
    return rc;

638
639
  for (i = 0; i < 2; ++i) {
    const int pf = i ? PF_INET : PF_INET6;
640
641
642
643
644
645
646
647
648
649
650
651
652
    for (j=0; j < 3; ++j) {
      const int type     = (j == 0) ? SOCK_STREAM :
                                      SOCK_DGRAM;
      const int protocol = (j == 0) ? IPPROTO_TCP :
                           (j == 1) ? IPPROTO_IP :
                                      IPPROTO_UDP;
      rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
        SCMP_CMP(0, SCMP_CMP_EQ, pf),
        SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, type),
        SCMP_CMP(2, SCMP_CMP_EQ, protocol));
      if (rc)
        return rc;
    }
653
  }
Cristian Toader's avatar
Cristian Toader committed
654

655
656
657
658
659
660
661
662
663
#ifdef ENABLE_NSS
  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
    SCMP_CMP(0, SCMP_CMP_EQ, PF_INET),
    SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM),
    SCMP_CMP(2, SCMP_CMP_EQ, IPPROTO_IP));
  if (rc)
    return rc;
#endif

664
665
666
667
  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_STREAM),
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
668
669
670
671
672
673
674
675
676
  if (rc)
    return rc;

  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
      SCMP_CMP(0, SCMP_CMP_EQ, PF_UNIX),
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC|SOCK_NONBLOCK, SOCK_DGRAM),
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
  if (rc)
    return rc;
677

678
  rc = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket),
679
      SCMP_CMP(0, SCMP_CMP_EQ, PF_NETLINK),
680
      SCMP_CMP_MASKED(1, SOCK_CLOEXEC, SOCK_RAW),
681
      SCMP_CMP(2, SCMP_CMP_EQ, 0));
682
683
684
685
686
687
  if (rc)
    return rc;

  return 0;
}

688
689
690
691
/**
 * Function responsible for setting up the socketpair syscall for
 * the seccomp filter sandbox.
 */
Cristian Toader's avatar
Cristian Toader committed
692
693
694
695
static int
sb_socketpair(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc = 0;
696
  (void) filter;
Cristian Toader's avatar
Cristian Toader committed
697
698

#ifdef __i386__
699
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair));
Cristian Toader's avatar
Cristian Toader committed
700
701
702
703
  if (rc)
    return rc;
#endif

704
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair),
Cristian Toader's avatar
Cristian Toader committed
705
706
707
708
709
710
711
712
      SCMP_CMP(0, SCMP_CMP_EQ, PF_FILE),
      SCMP_CMP(1, SCMP_CMP_EQ, SOCK_STREAM|SOCK_CLOEXEC));
  if (rc)
    return rc;

  return 0;
}

713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
#ifdef HAVE_KIST_SUPPORT

#include <linux/sockios.h>

static int
sb_ioctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
{
  int rc;
  (void) filter;

  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl),
                          SCMP_CMP(1, SCMP_CMP_EQ, SIOCOUTQNSD));
  if (rc)
    return rc;
  return 0;
}

730
#endif /* defined(HAVE_KIST_SUPPORT) */
731

732
733
734
735
/**
 * Function responsible for setting up the setsockopt syscall for
 * the seccomp filter sandbox.
 */
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
736
static int
737
sb_setsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
738
739
{
  int rc = 0;
740
  (void) filter;
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
741

Cristian Toader's avatar
Cristian Toader committed
742
#ifdef __i386__
743
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt));
Cristian Toader's avatar
Cristian Toader committed
744
745
746
747
  if (rc)
    return rc;
#endif

748
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
749
750
751
752
753
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
      SCMP_CMP(2, SCMP_CMP_EQ, SO_REUSEADDR));
  if (rc)
    return rc;

754
755
756
757
758
759
760
761
762
763
764
765
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
      SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
  if (rc)
    return rc;

  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
      SCMP_CMP(2, SCMP_CMP_EQ, SO_RCVBUF));
  if (rc)
    return rc;

766
767
768
769
770
771
#ifdef HAVE_SYSTEMD
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
      SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUFFORCE));
  if (rc)
    return rc;
772
#endif /* defined(HAVE_SYSTEMD) */
773

774
#ifdef IP_TRANSPARENT
775
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
776
777
778
779
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
      SCMP_CMP(2, SCMP_CMP_EQ, IP_TRANSPARENT));
  if (rc)
    return rc;
780
#endif /* defined(IP_TRANSPARENT) */
781

782
783
784
785
786
787
#ifdef IPV6_V6ONLY
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(setsockopt),
      SCMP_CMP(1, SCMP_CMP_EQ, IPPROTO_IPV6),
      SCMP_CMP(2, SCMP_CMP_EQ, IPV6_V6ONLY));
  if (rc)
    return rc;
788
#endif /* defined(IPV6_V6ONLY) */
789

Cristian Toader's avatar
fcntl64    
Cristian Toader committed
790
791
792
  return 0;
}

793
794
795
796
/**
 * Function responsible for setting up the getsockopt syscall for
 * the seccomp filter sandbox.
 */
Cristian Toader's avatar
Cristian Toader committed
797
798
static int
sb_getsockopt(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
Cristian Toader's avatar
Cristian Toader committed
799
800
{
  int rc = 0;
801
  (void) filter;
Cristian Toader's avatar
Cristian Toader committed
802
803

#ifdef __i386__
804
  rc = seccomp_rule_add_0(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt));
Cristian Toader's avatar
Cristian Toader committed
805
806
807
808
  if (rc)
    return rc;
#endif

809
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
Cristian Toader's avatar
Cristian Toader committed
810
811
812
813
814
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
      SCMP_CMP(2, SCMP_CMP_EQ, SO_ERROR));
  if (rc)
    return rc;

815
816
817
818
819
820
#ifdef HAVE_SYSTEMD
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_SOCKET),
      SCMP_CMP(2, SCMP_CMP_EQ, SO_SNDBUF));
  if (rc)
    return rc;
821
#endif /* defined(HAVE_SYSTEMD) */
822

823
824
825
826
827
828
#ifdef HAVE_LINUX_NETFILTER_IPV4_H
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_IP),
      SCMP_CMP(2, SCMP_CMP_EQ, SO_ORIGINAL_DST));
  if (rc)
    return rc;
829
#endif /* defined(HAVE_LINUX_NETFILTER_IPV4_H) */
830
831
832
833
834
835
836

#ifdef HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_IPV6),
      SCMP_CMP(2, SCMP_CMP_EQ, IP6T_SO_ORIGINAL_DST));
  if (rc)
    return rc;
837
#endif /* defined(HAVE_LINUX_NETFILTER_IPV6_IP6_TABLES_H) */
838

839
840
841
842
843
844
845
#ifdef HAVE_KIST_SUPPORT
#include <netinet/tcp.h>
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(getsockopt),
      SCMP_CMP(1, SCMP_CMP_EQ, SOL_TCP),
      SCMP_CMP(2, SCMP_CMP_EQ, TCP_INFO));
  if (rc)
    return rc;
846
#endif /* defined(HAVE_KIST_SUPPORT) */
847

Cristian Toader's avatar
Cristian Toader committed
848
849
850
  return 0;
}

Cristian Toader's avatar
fcntl64    
Cristian Toader committed
851
#ifdef __NR_fcntl64
852
853
854
855
/**
 * Function responsible for setting up the fcntl64 syscall for
 * the seccomp filter sandbox.
 */
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
856
static int
857
sb_fcntl64(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
858
859
{
  int rc = 0;
Nick Mathewson's avatar
Nick Mathewson committed
860
  (void) filter;
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
861

862
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
863
864
865
866
      SCMP_CMP(1, SCMP_CMP_EQ, F_GETFL));
  if (rc)
    return rc;

867
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
868
869
870
871
872
      SCMP_CMP(1, SCMP_CMP_EQ, F_SETFL),
      SCMP_CMP(2, SCMP_CMP_EQ, O_RDWR|O_NONBLOCK));
  if (rc)
    return rc;

873
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
874
875
876
877
      SCMP_CMP(1, SCMP_CMP_EQ, F_GETFD));
  if (rc)
    return rc;

878
  rc = seccomp_rule_add_2(ctx, SCMP_ACT_ALLOW, SCMP_SYS(fcntl64),
879
880
881
882
883
      SCMP_CMP(1, SCMP_CMP_EQ, F_SETFD),
      SCMP_CMP(2, SCMP_CMP_EQ, FD_CLOEXEC));
  if (rc)
    return rc;

Cristian Toader's avatar
fcntl64    
Cristian Toader committed
884
885
  return 0;
}
886
#endif /* defined(__NR_fcntl64) */
Cristian Toader's avatar
fcntl64    
Cristian Toader committed
887

888
889
890
891
892
893
/**
 * Function responsible for setting up the epoll_ctl syscall for
 * the seccomp filter sandbox.
 *
 *  Note: basically allows everything but will keep for now..
 */
Cristian Toader's avatar
Cristian Toader committed
894
static int
895
sb_epoll_ctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
Cristian Toader's avatar
Cristian Toader committed
896
897
{
  int rc = 0;
898
  (void) filter;
Cristian Toader's avatar
Cristian Toader committed
899

900
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
Cristian Toader's avatar
Cristian Toader committed
901
902
903
904
      SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_ADD));
  if (rc)
    return rc;

905
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
Cristian Toader's avatar
Cristian Toader committed
906
907
908
909
      SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_MOD));
  if (rc)
    return rc;

910
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(epoll_ctl),
Cristian Toader's avatar
Cristian Toader committed
911
912
913
914
      SCMP_CMP(1, SCMP_CMP_EQ, EPOLL_CTL_DEL));
  if (rc)
    return rc;

Cristian Toader's avatar
Cristian Toader committed
915
916
917
  return 0;
}

918
/**
919
 * Function responsible for setting up the prctl syscall for
920
921
922
923
 * the seccomp filter sandbox.
 *
 * NOTE: if multiple filters need to be added, the PR_SECCOMP parameter needs
 * to be whitelisted in this function.
924
925
 */
static int
926
sb_prctl(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
927
928
{
  int rc = 0;
929
  (void) filter;
930

931
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl),
932
933
934
935
936
937
938
939
      SCMP_CMP(0, SCMP_CMP_EQ, PR_SET_DUMPABLE));
  if (rc)
    return rc;

  return 0;
}

/**
940
 * Function responsible for setting up the mprotect syscall for
941
942
943
944
 * the seccomp filter sandbox.
 *
 * NOTE: does not NEED to be here.. currently only occurs before filter; will
 * keep just in case for the future.
945
946
 */
static int
947
sb_mprotect(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
948
949
{
  int rc = 0;
950
  (void) filter;
951

952
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
953
954
955
956
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ));
  if (rc)
    return rc;

957
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect),
958
959
960
961
      SCMP_CMP(2, SCMP_CMP_EQ, PROT_NONE));
  if (rc)
    return rc;

962
963
964
  return 0;
}

965
966
967
968
/**
 * Function responsible for setting up the rt_sigprocmask syscall for
 * the seccomp filter sandbox.
 */
969
static int
970
sb_rt_sigprocmask(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
971
972
{
  int rc = 0;
973
  (void) filter;
974

975
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
976
977
978
979
      SCMP_CMP(0, SCMP_CMP_EQ, SIG_UNBLOCK));
  if (rc)
    return rc;

980
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigprocmask),
981
982
983
984
      SCMP_CMP(0, SCMP_CMP_EQ, SIG_SETMASK));
  if (rc)
    return rc;

985
986
987
988
  return 0;
}

/**
989
990
991
992
 * Function responsible for setting up the flock syscall for
 * the seccomp filter sandbox.
 *
 *  NOTE: does not need to be here, occurs before filter is applied.
993
994
 */
static int
995
sb_flock(scmp_filter_ctx ctx, sandbox_cfg_t *filter)
996
997
{
  int rc = 0;
998
  (void) filter;
999

1000
  rc = seccomp_rule_add_1(ctx, SCMP_ACT_ALLOW, SCMP_SYS(flock),
For faster browsing, not all history is shown. View entire blame