1# Copyright 2021 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from optparse import OptionParser 16from optparse import Option, OptionValueError 17import os 18import policy 19import re 20import sys 21 22SHARED_LIB_EXTENSION = '.dylib' if sys.platform == 'darwin' else '.so' 23 24############################################################# 25# Tests 26############################################################# 27def TestDataTypeViolations(pol): 28 return pol.AssertPathTypesHaveAttr(["/data/"], [], "data_file_type") 29 30def TestSystemTypeViolations(pol): 31 partitions = ["/system/", "/system_ext/", "/product/"] 32 exceptions = [ 33 # devices before treble don't have a vendor partition 34 "/system/vendor/", 35 36 # overlay files are mounted over vendor 37 "/product/overlay/", 38 "/product/vendor_overlay/", 39 "/system/overlay/", 40 "/system/product/overlay/", 41 "/system/product/vendor_overlay/", 42 "/system/system_ext/overlay/", 43 "/system_ext/overlay/", 44 ] 45 46 return pol.AssertPathTypesHaveAttr(partitions, exceptions, "system_file_type") 47 48def TestBpffsTypeViolations(pol): 49 return pol.AssertGenfsFilesystemTypesHaveAttr("bpf", "bpffs_type") 50 51def TestProcTypeViolations(pol): 52 return pol.AssertGenfsFilesystemTypesHaveAttr("proc", "proc_type") 53 54def TestSysfsTypeViolations(pol): 55 ret = pol.AssertGenfsFilesystemTypesHaveAttr("sysfs", "sysfs_type") 56 ret += pol.AssertPathTypesHaveAttr(["/sys/"], ["/sys/kernel/debug/", 57 "/sys/kernel/tracing"], "sysfs_type") 58 return ret 59 60def TestDebugfsTypeViolations(pol): 61 ret = pol.AssertGenfsFilesystemTypesHaveAttr("debugfs", "debugfs_type") 62 ret += pol.AssertPathTypesHaveAttr(["/sys/kernel/debug/", 63 "/sys/kernel/tracing"], [], "debugfs_type") 64 return ret 65 66def TestTracefsTypeViolations(pol): 67 ret = pol.AssertGenfsFilesystemTypesHaveAttr("tracefs", "tracefs_type") 68 ret += pol.AssertPathTypesHaveAttr(["/sys/kernel/tracing"], [], "tracefs_type") 69 ret += pol.AssertPathTypesDoNotHaveAttr(["/sys/kernel/debug"], 70 ["/sys/kernel/debug/tracing"], "tracefs_type", 71 []) 72 return ret 73 74def TestVendorTypeViolations(pol): 75 partitions = ["/vendor/", "/odm/"] 76 exceptions = [ 77 "/vendor/etc/selinux/", 78 "/vendor/odm/etc/selinux/", 79 "/odm/etc/selinux/", 80 ] 81 return pol.AssertPathTypesHaveAttr(partitions, exceptions, "vendor_file_type") 82 83def TestCoreDataTypeViolations(pol): 84 return pol.AssertPathTypesHaveAttr(["/data/"], ["/data/vendor", 85 "/data/vendor_ce", "/data/vendor_de"], "core_data_file_type") 86 87def TestPropertyTypeViolations(pol): 88 return pol.AssertPropertyOwnersAreExclusive() 89 90def TestAppDataTypeViolations(pol): 91 # Types with the app_data_file_type should only be used for app data files 92 # (/data/data/package.name etc) via seapp_contexts, and never applied 93 # explicitly to other files. 94 partitions = [ 95 "/data/", 96 "/vendor/", 97 "/odm/", 98 "/product/", 99 ] 100 exceptions = [ 101 # These are used for app data files for the corresponding user and 102 # assorted other files. 103 # TODO(b/172812577): Use different types for the different purposes 104 "shell_data_file", 105 "bluetooth_data_file", 106 "nfc_data_file", 107 "radio_data_file", 108 ] 109 return pol.AssertPathTypesDoNotHaveAttr(partitions, [], "app_data_file_type", 110 exceptions) 111def TestDmaHeapDevTypeViolations(pol): 112 return pol.AssertPathTypesHaveAttr(["/dev/dma_heap/"], [], 113 "dmabuf_heap_device_type") 114 115 116 117### 118# extend OptionParser to allow the same option flag to be used multiple times. 119# This is used to allow multiple file_contexts files and tests to be 120# specified. 121# 122class MultipleOption(Option): 123 ACTIONS = Option.ACTIONS + ("extend",) 124 STORE_ACTIONS = Option.STORE_ACTIONS + ("extend",) 125 TYPED_ACTIONS = Option.TYPED_ACTIONS + ("extend",) 126 ALWAYS_TYPED_ACTIONS = Option.ALWAYS_TYPED_ACTIONS + ("extend",) 127 128 def take_action(self, action, dest, opt, value, values, parser): 129 if action == "extend": 130 values.ensure_value(dest, []).append(value) 131 else: 132 Option.take_action(self, action, dest, opt, value, values, parser) 133 134Tests = [ 135 "TestBpffsTypeViolations", 136 "TestDataTypeViolators", 137 "TestProcTypeViolations", 138 "TestSysfsTypeViolations", 139 "TestSystemTypeViolators", 140 "TestDebugfsTypeViolations", 141 "TestTracefsTypeViolations", 142 "TestVendorTypeViolations", 143 "TestCoreDataTypeViolations", 144 "TestPropertyTypeViolations", 145 "TestAppDataTypeViolations", 146 "TestDmaHeapDevTypeViolations", 147] 148 149if __name__ == '__main__': 150 usage = "sepolicy_tests -f vendor_file_contexts -f " 151 usage +="plat_file_contexts -p policy [--test test] [--help]" 152 parser = OptionParser(option_class=MultipleOption, usage=usage) 153 parser.add_option("-f", "--file_contexts", dest="file_contexts", 154 metavar="FILE", action="extend", type="string") 155 parser.add_option("-p", "--policy", dest="policy", metavar="FILE") 156 parser.add_option("-t", "--test", dest="test", action="extend", 157 help="Test options include "+str(Tests)) 158 159 (options, args) = parser.parse_args() 160 161 libpath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 162 "libsepolwrap" + SHARED_LIB_EXTENSION) 163 if not os.path.exists(libpath): 164 sys.exit("Error: libsepolwrap does not exist. Is this binary corrupted?\n") 165 166 if not options.policy: 167 sys.exit("Must specify monolithic policy file\n" + parser.usage) 168 if not os.path.exists(options.policy): 169 sys.exit("Error: policy file " + options.policy + " does not exist\n" 170 + parser.usage) 171 172 if not options.file_contexts: 173 sys.exit("Error: Must specify file_contexts file(s)\n" + parser.usage) 174 for f in options.file_contexts: 175 if not os.path.exists(f): 176 sys.exit("Error: File_contexts file " + f + " does not exist\n" + 177 parser.usage) 178 179 pol = policy.Policy(options.policy, options.file_contexts, libpath) 180 181 results = "" 182 # If an individual test is not specified, run all tests. 183 if options.test is None or "TestBpffsTypeViolations" in options.test: 184 results += TestBpffsTypeViolations(pol) 185 if options.test is None or "TestDataTypeViolations" in options.test: 186 results += TestDataTypeViolations(pol) 187 if options.test is None or "TestProcTypeViolations" in options.test: 188 results += TestProcTypeViolations(pol) 189 if options.test is None or "TestSysfsTypeViolations" in options.test: 190 results += TestSysfsTypeViolations(pol) 191 if options.test is None or "TestSystemTypeViolations" in options.test: 192 results += TestSystemTypeViolations(pol) 193 if options.test is None or "TestDebugfsTypeViolations" in options.test: 194 results += TestDebugfsTypeViolations(pol) 195 if options.test is None or "TestTracefsTypeViolations" in options.test: 196 results += TestTracefsTypeViolations(pol) 197 if options.test is None or "TestVendorTypeViolations" in options.test: 198 results += TestVendorTypeViolations(pol) 199 if options.test is None or "TestCoreDataTypeViolations" in options.test: 200 results += TestCoreDataTypeViolations(pol) 201 if options.test is None or "TestPropertyTypeViolations" in options.test: 202 results += TestPropertyTypeViolations(pol) 203 if options.test is None or "TestAppDataTypeViolations" in options.test: 204 results += TestAppDataTypeViolations(pol) 205 if options.test is None or "TestDmaHeapDevTypeViolations" in options.test: 206 results += TestDmaHeapDevTypeViolations(pol) 207 208 if len(results) > 0: 209 sys.exit(results) 210