1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "seccomp_policy.h" 18 19 #include <assert.h> 20 #include <linux/audit.h> 21 #include <linux/seccomp.h> 22 #include <sys/prctl.h> 23 24 #include <vector> 25 26 #include <android-base/logging.h> 27 28 #include "seccomp_bpfs.h" 29 30 31 #if defined __arm__ || defined __aarch64__ 32 33 #define DUAL_ARCH 34 #define PRIMARY_ARCH AUDIT_ARCH_AARCH64 35 static const struct sock_filter* primary_app_filter = arm64_app_filter; 36 static const size_t primary_app_filter_size = arm64_app_filter_size; 37 static const struct sock_filter* primary_system_filter = arm64_system_filter; 38 static const size_t primary_system_filter_size = arm64_system_filter_size; 39 static const struct sock_filter* primary_global_filter = arm64_global_filter; 40 static const size_t primary_global_filter_size = arm64_global_filter_size; 41 #define SECONDARY_ARCH AUDIT_ARCH_ARM 42 static const struct sock_filter* secondary_app_filter = arm_app_filter; 43 static const size_t secondary_app_filter_size = arm_app_filter_size; 44 static const struct sock_filter* secondary_system_filter = arm_system_filter; 45 static const size_t secondary_system_filter_size = arm_system_filter_size; 46 static const struct sock_filter* secondary_global_filter = arm_global_filter; 47 static const size_t secondary_global_filter_size = arm_global_filter_size; 48 49 #elif defined __i386__ || defined __x86_64__ 50 51 #define DUAL_ARCH 52 #define PRIMARY_ARCH AUDIT_ARCH_X86_64 53 static const struct sock_filter* primary_app_filter = x86_64_app_filter; 54 static const size_t primary_app_filter_size = x86_64_app_filter_size; 55 static const struct sock_filter* primary_system_filter = x86_64_system_filter; 56 static const size_t primary_system_filter_size = x86_64_system_filter_size; 57 static const struct sock_filter* primary_global_filter = x86_64_global_filter; 58 static const size_t primary_global_filter_size = x86_64_global_filter_size; 59 #define SECONDARY_ARCH AUDIT_ARCH_I386 60 static const struct sock_filter* secondary_app_filter = x86_app_filter; 61 static const size_t secondary_app_filter_size = x86_app_filter_size; 62 static const struct sock_filter* secondary_system_filter = x86_system_filter; 63 static const size_t secondary_system_filter_size = x86_system_filter_size; 64 static const struct sock_filter* secondary_global_filter = x86_global_filter; 65 static const size_t secondary_global_filter_size = x86_global_filter_size; 66 67 #elif defined __mips__ || defined __mips64__ 68 69 #define DUAL_ARCH 70 #define PRIMARY_ARCH AUDIT_ARCH_MIPSEL64 71 static const struct sock_filter* primary_app_filter = mips64_app_filter; 72 static const size_t primary_app_filter_size = mips64_app_filter_size; 73 static const struct sock_filter* primary_system_filter = mips64_system_filter; 74 static const size_t primary_system_filter_size = mips64_system_filter_size; 75 static const struct sock_filter* primary_global_filter = mips64_global_filter; 76 static const size_t primary_global_filter_size = mips64_global_filter_size; 77 #define SECONDARY_ARCH AUDIT_ARCH_MIPSEL 78 static const struct sock_filter* secondary_app_filter = mips_app_filter; 79 static const size_t secondary_app_filter_size = mips_app_filter_size; 80 static const struct sock_filter* secondary_system_filter = mips_system_filter; 81 static const size_t secondary_system_filter_size = mips_system_filter_size; 82 static const struct sock_filter* secondary_global_filter = mips_global_filter; 83 static const size_t secondary_global_filter_size = mips_global_filter_size; 84 85 #else 86 #error No architecture was defined! 87 #endif 88 89 90 #define syscall_nr (offsetof(struct seccomp_data, nr)) 91 #define arch_nr (offsetof(struct seccomp_data, arch)) 92 93 typedef std::vector<sock_filter> filter; 94 95 inline void Disallow(filter& f) { 96 f.push_back(BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRAP)); 97 } 98 99 static void ExamineSyscall(filter& f) { 100 f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, syscall_nr)); 101 } 102 103 #ifdef DUAL_ARCH 104 static bool SetValidateArchitectureJumpTarget(size_t offset, filter& f) { 105 size_t jump_length = f.size() - offset - 1; 106 auto u8_jump_length = (__u8) jump_length; 107 if (u8_jump_length != jump_length) { 108 LOG(FATAL) 109 << "Can't set jump greater than 255 - actual jump is " << jump_length; 110 return false; 111 } 112 f[offset] = BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, SECONDARY_ARCH, u8_jump_length, 0); 113 return true; 114 } 115 116 static size_t ValidateArchitectureAndJumpIfNeeded(filter& f) { 117 f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, arch_nr)); 118 f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, PRIMARY_ARCH, 2, 0)); 119 f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, SECONDARY_ARCH, 1, 0)); 120 Disallow(f); 121 return f.size() - 2; 122 } 123 #else 124 static void ValidateArchitecture(filter& f) { 125 f.push_back(BPF_STMT(BPF_LD|BPF_W|BPF_ABS, arch_nr)); 126 f.push_back(BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, PRIMARY_ARCH, 1, 0)); 127 Disallow(f); 128 } 129 #endif 130 131 static bool install_filter(filter const& f) { 132 struct sock_fprog prog = { 133 static_cast<unsigned short>(f.size()), 134 const_cast<struct sock_filter*>(&f[0]), 135 }; 136 // This assumes either the current process has CAP_SYS_ADMIN, or PR_SET_NO_NEW_PRIVS bit is set. 137 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0) { 138 PLOG(FATAL) << "Could not set seccomp filter of size " << f.size(); 139 return false; 140 } 141 return true; 142 } 143 144 enum FilterType { 145 APP, 146 SYSTEM, 147 GLOBAL 148 }; 149 150 bool _set_seccomp_filter(FilterType type) { 151 const sock_filter *p, *s; 152 size_t p_size, s_size; 153 filter f; 154 155 switch (type) { 156 case APP: 157 p = primary_app_filter; 158 p_size = primary_app_filter_size; 159 s = secondary_app_filter; 160 s_size = secondary_app_filter_size; 161 break; 162 case SYSTEM: 163 p = primary_system_filter; 164 p_size = primary_system_filter_size; 165 s = secondary_system_filter; 166 s_size = secondary_system_filter_size; 167 break; 168 case GLOBAL: 169 p = primary_global_filter; 170 p_size = primary_global_filter_size; 171 s = secondary_global_filter; 172 s_size = secondary_global_filter_size; 173 break; 174 175 } 176 177 #ifdef DUAL_ARCH 178 // Note that for mixed 64/32 bit architectures, ValidateArchitecture inserts a 179 // jump that must be changed to point to the start of the 32-bit policy 180 // 32 bit syscalls will not hit the policy between here and the call to SetJump 181 auto offset_to_secondary_filter = ValidateArchitectureAndJumpIfNeeded(f); 182 #else 183 ValidateArchitecture(f); 184 #endif 185 186 ExamineSyscall(f); 187 188 for (size_t i = 0; i < p_size; ++i) { 189 f.push_back(p[i]); 190 } 191 Disallow(f); 192 193 #ifdef DUAL_ARCH 194 if (!SetValidateArchitectureJumpTarget(offset_to_secondary_filter, f)) { 195 return false; 196 } 197 198 ExamineSyscall(f); 199 200 for (size_t i = 0; i < s_size; ++i) { 201 f.push_back(s[i]); 202 } 203 Disallow(f); 204 #endif 205 206 return install_filter(f); 207 } 208 209 bool set_app_seccomp_filter() { 210 return _set_seccomp_filter(FilterType::APP); 211 } 212 213 bool set_system_seccomp_filter() { 214 return _set_seccomp_filter(FilterType::SYSTEM); 215 } 216 217 bool set_global_seccomp_filter() { 218 return _set_seccomp_filter(FilterType::GLOBAL); 219 } 220