1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
// Copyright 2020 syzkaller project authors. All rights reserved.
// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
// These headers are generated by the Android build system and need to be updated periodically.
// Header files are generated by `genseccomp.py`
// (https://android.googlesource.com/platform/bionic/+/refs/heads/main/libc/tools/genseccomp.py).
// Arguments are taken from the android build file
// (https://android.googlesource.com/platform/bionic/+/refs/heads/main/libc/Android.bp).
#if GOARCH_arm64
#define PRIMARY_ARCH AUDIT_ARCH_AARCH64
#include "arm64_app_policy.h"
static const struct sock_filter* primary_app_filter = arm64_app_filter;
static const size_t primary_app_filter_size = arm64_app_filter_size;
#include "arm64_system_policy.h"
static const struct sock_filter* system_filter = arm64_system_filter;
static const size_t system_filter_size = arm64_system_filter_size;
// We need 3 for ValidateArchitecture and 1 for ExamineSyscall and 4 for ValidateArchitectureAndJumpIfNeeded + 2 extra Disallow
#define kFilterMaxSize (arm64_app_filter_size + 3 + 1 + 4 + 2)
#elif GOARCH_arm
#define PRIMARY_ARCH AUDIT_ARCH_ARM
#include "arm_app_policy.h"
static const struct sock_filter* primary_app_filter = arm_app_filter;
static const size_t primary_app_filter_size = arm_app_filter_size;
#include "arm_system_policy.h"
static const struct sock_filter* system_filter = arm_system_filter;
static const size_t system_filter_size = arm_system_filter_size;
#define kFilterMaxSize (arm_app_filter_size + 3 + 1 + 4 + 2)
// Note: clone3() and set/get_robust_list() are added as they are used
// by pthread_create().
#elif GOARCH_amd64
#define PRIMARY_ARCH AUDIT_ARCH_X86_64
#include "x86_64_app_policy.h"
static const struct sock_filter* primary_app_filter = x86_64_app_filter;
static const size_t primary_app_filter_size = x86_64_app_filter_size;
#include "x86_64_system_policy.h"
static const struct sock_filter* system_filter = x86_64_system_filter;
static const size_t system_filter_size = x86_64_system_filter_size;
#define kFilterMaxSize (x86_64_app_filter_size + 3 + 1 + 4 + 2)
#elif GOARCH_386
#define PRIMARY_ARCH AUDIT_ARCH_I386
#include "x86_app_policy.h"
static const struct sock_filter* primary_app_filter = x86_app_filter;
static const size_t primary_app_filter_size = x86_app_filter_size;
#include "x86_system_policy.h"
static const struct sock_filter* system_filter = x86_system_filter;
static const size_t system_filter_size = x86_system_filter_size;
#define kFilterMaxSize (x86_app_filter_size + 3 + 1 + 4 + 2)
#else
#error No architecture was defined!
#endif
#define syscall_nr (offsetof(struct seccomp_data, nr))
#define arch_nr (offsetof(struct seccomp_data, arch))
typedef struct Filter_t {
struct sock_filter data[kFilterMaxSize];
size_t count;
} Filter;
static void push_back(Filter* filter_array, struct sock_filter filter)
{
if (filter_array->count == kFilterMaxSize)
failmsg("can't add another syscall to seccomp filter", "count=%zu", filter_array->count);
filter_array->data[filter_array->count++] = filter;
}
static void Disallow(Filter* f)
{
struct sock_filter filter = BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP);
push_back(f, filter);
}
static void ExamineSyscall(Filter* f)
{
struct sock_filter filter = BPF_STMT(BPF_LD | BPF_W | BPF_ABS, syscall_nr);
push_back(f, filter);
}
static void ValidateArchitecture(Filter* f)
{
struct sock_filter filter1 = BPF_STMT(BPF_LD | BPF_W | BPF_ABS, arch_nr);
struct sock_filter filter2 = BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, PRIMARY_ARCH, 1, 0);
push_back(f, filter1);
push_back(f, filter2);
Disallow(f);
}
// Modified from the orignal Android code to fail instead of return.
static void install_filter(const Filter* f)
{
struct sock_fprog prog = {
(unsigned short)f->count,
(struct sock_filter*)&f->data[0],
};
// This assumes either the current process has CAP_SYS_ADMIN, or PR_SET_NO_NEW_PRIVS bit is set.
if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0)
failmsg("could not set seccomp filter", "size=%zu", f->count);
}
// Modified from the original Android code as we don't need dual arch support
static void set_seccomp_filter(const struct sock_filter* filter, size_t size)
{
Filter f;
f.count = 0;
ValidateArchitecture(&f);
ExamineSyscall(&f);
for (size_t i = 0; i < size; ++i)
push_back(&f, filter[i]);
Disallow(&f);
// Will fail() if anything fails.
install_filter(&f);
}
enum {
SCFS_RestrictedApp,
SCFS_SystemAccount
};
static void set_app_seccomp_filter(int account)
{
if (account == SCFS_SystemAccount) {
set_seccomp_filter(system_filter, system_filter_size);
} else {
set_seccomp_filter(primary_app_filter, primary_app_filter_size);
}
}
|