diff options
Diffstat (limited to 'executor/android/android_seccomp.h')
| -rw-r--r-- | executor/android/android_seccomp.h | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/executor/android/android_seccomp.h b/executor/android/android_seccomp.h new file mode 100644 index 000000000..21fd723e3 --- /dev/null +++ b/executor/android/android_seccomp.h @@ -0,0 +1,111 @@ +// Copyright 2016 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 syscall_arg(_n) (offsetof(struct seccomp_data, args[_n])) +#define arch_nr (offsetof(struct seccomp_data, arch)) + + +typedef struct Filter_t { + struct sock_filter data[kFilterMaxSize]; + size_t count; +} Filter; + +inline 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; +} + +inline 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 +void set_app_seccomp_filter() +{ + const struct sock_filter *p; + size_t p_size; + Filter f; + f.count = 0; + + p = primary_app_filter; + p_size = primary_app_filter_size; + + 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); +} |
