aboutsummaryrefslogtreecommitdiffstats
path: root/executor/android/android_seccomp.h
blob: d8df52792c81d0b4f207194e4b1a586b15b61652 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// 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.
#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;
// 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;
#define kFilterMaxSize (arm_app_filter_size + 3 + 1 + 4 + 2)

#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;
#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;
#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)
		fail("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) {
		fail("Could not set seccomp filter of size %zu", f->count);
	}
}

// Modified from the orignal Android code as we don't need dual arch support
static void set_app_seccomp_filter()
{
	const struct sock_filter* p = primary_app_filter;
	size_t p_size = primary_app_filter_size;

	Filter f;
	f.count = 0;
	ValidateArchitecture(&f);
	ExamineSyscall(&f);

	for (size_t i = 0; i < p_size; ++i)
		push_back(&f, p[i]);
	Disallow(&f);

	// Will fail() if anything fails.
	install_filter(&f);
}