| // 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); |
| } |
| } |