Merge "Add property context for persist.bluetooth.sniff_offload" into main
diff --git a/apex/com.android.biometrics.virtual.face-file_contexts b/apex/com.android.biometrics.virtual.face-file_contexts
index 07fc0a8..8d9b86c 100644
--- a/apex/com.android.biometrics.virtual.face-file_contexts
+++ b/apex/com.android.biometrics.virtual.face-file_contexts
@@ -1,3 +1,3 @@
-(/.*)?                                          u:object_r:vendor_file:s0
-/etc(/.*)?                                      u:object_r:vendor_configs_file:s0
+(/.*)?                                          u:object_r:system_file:s0
+/lib(64)?(/.*)                                  u:object_r:system_lib_file:s0
 /bin/hw/android\.hardware\.biometrics\.face-service\.example u:object_r:virtual_face_exec:s0
diff --git a/build/soong/service_fuzzer_bindings.go b/build/soong/service_fuzzer_bindings.go
index 257cee6..bcdfaef 100644
--- a/build/soong/service_fuzzer_bindings.go
+++ b/build/soong/service_fuzzer_bindings.go
@@ -292,7 +292,6 @@
 		"fingerprint":                                                         EXCEPTION_NO_FUZZER,
 		"feature_flags":                                                       EXCEPTION_NO_FUZZER,
 		"font":                                                                EXCEPTION_NO_FUZZER,
-		"forensic":                                                            EXCEPTION_NO_FUZZER,
 		"android.hardware.fingerprint.IFingerprintDaemon": EXCEPTION_NO_FUZZER,
 		"game":                                   EXCEPTION_NO_FUZZER,
 		"gfxinfo":                                EXCEPTION_NO_FUZZER,
diff --git a/private/dumpstate.te b/private/dumpstate.te
index a1c9ed3..6a16790 100644
--- a/private/dumpstate.te
+++ b/private/dumpstate.te
@@ -462,6 +462,7 @@
   -hal_service_type
   -virtual_touchpad_service
   -vold_service
+  -fwk_vold_service
   -default_android_service
 }:service_manager find;
 # suppress denials for services dumpstate should not be accessing.
@@ -472,6 +473,7 @@
   hal_service_type
   virtual_touchpad_service
   vold_service
+  fwk_vold_service
 }:service_manager find;
 
 # Most of these are neverallowed.
diff --git a/private/service_contexts b/private/service_contexts
index e2998c7..4b35a42 100644
--- a/private/service_contexts
+++ b/private/service_contexts
@@ -279,9 +279,6 @@
 file_integrity                            u:object_r:file_integrity_service:s0
 fingerprint                               u:object_r:fingerprint_service:s0
 font                                      u:object_r:font_service:s0
-starting_at_board_api(202504, `
-    forensic                                  u:object_r:forensic_service:s0
-')
 android.hardware.fingerprint.IFingerprintDaemon u:object_r:fingerprintd_service:s0
 game                                      u:object_r:game_service:s0
 gfxinfo                                   u:object_r:gfxinfo_service:s0
diff --git a/public/service.te b/public/service.te
index 68f4ea0..d0f03c8 100644
--- a/public/service.te
+++ b/public/service.te
@@ -144,9 +144,6 @@
 type platform_compat_service, app_api_service, ephemeral_app_api_service, system_server_service, service_manager_type;
 type face_service, app_api_service, system_server_service, service_manager_type;
 type fingerprint_service, app_api_service, system_server_service, service_manager_type;
-starting_at_board_api(202504, `
-    type forensic_service, app_api_service, system_api_service, system_server_service, service_manager_type;
-')
 type fwk_altitude_service, system_server_service, service_manager_type;
 type fwk_stats_service, app_api_service, system_server_service, service_manager_type;
 type fwk_sensor_service, system_server_service, service_manager_type;
diff --git a/tests/apex_sepolicy_tests.py b/tests/apex_sepolicy_tests.py
index 26082cb..d8c5c2b 100644
--- a/tests/apex_sepolicy_tests.py
+++ b/tests/apex_sepolicy_tests.py
@@ -29,7 +29,7 @@
 import sys
 import tempfile
 from dataclasses import dataclass
-from typing import List
+from typing import Callable, List
 
 import policy
 
@@ -61,7 +61,12 @@
     pass
 
 
-Matcher = Is | Glob | Regex | BinaryFile
+@dataclass
+class MatchPred:
+    pred: Callable[[str], bool]
+
+
+Matcher = Is | Glob | Regex | BinaryFile | MatchPred
 
 
 # predicate functions for Func matcher
@@ -87,7 +92,13 @@
     labels: set[str]
 
 
-Rule = AllowPerm | ResolveType | NotAnyOf
+@dataclass
+class HasAttr:
+    """Rule checking if the context has the specified attribute"""
+    attr: str
+
+
+Rule = AllowPerm | ResolveType | NotAnyOf | HasAttr
 
 
 # Helper for 'read'
@@ -104,8 +115,10 @@
             return pathlib.PurePath(path).match(pattern)
         case Regex(pattern):
             return re.match(pattern, path)
-        case BinaryFile:
+        case BinaryFile():
             return path.startswith('./bin/') and not path.endswith('/')
+        case MatchPred(pred):
+            return pred(path)
 
 
 def check_rule(pol, path: str, tcontext: str, rule: Rule) -> List[str]:
@@ -129,6 +142,9 @@
         case NotAnyOf(labels):
             if tcontext in labels:
                 errors.append(f"Error: {path}: can't be labelled as '{tcontext}'")
+        case HasAttr(attr):
+            if tcontext not in pol.QueryTypeAttribute(attr, True):
+                errors.append(f"Error: {path}: tcontext({tcontext}) must be associated with {attr}")
     return errors
 
 
@@ -139,7 +155,7 @@
 
 generic_rules = [
     # binaries should be executable
-    (BinaryFile, NotAnyOf({'vendor_file'})),
+    (BinaryFile(), NotAnyOf({'vendor_file'})),
     # permissions
     (Is('./etc/permissions/'), AllowRead('dir', {'system_server'})),
     (Glob('./etc/permissions/*.xml'), AllowRead('file', {'system_server'})),
@@ -159,6 +175,25 @@
 all_rules = target_specific_rules + generic_rules
 
 
+def base_attr_for(partition):
+    if partition in ['system', 'system_ext', 'product']:
+        return 'system_file_type'
+    elif partition in ['vendor', 'odm']:
+        return 'vendor_file_type'
+    else:
+        sys.exit(f"Error: invalid partition: {partition}\n")
+
+
+def system_vendor_rule(partition):
+    exceptions = [
+        "./etc/linkerconfig.pb"
+    ]
+    def pred(path):
+        return path not in exceptions
+
+    return pred, HasAttr(base_attr_for(partition))
+
+
 def check_line(pol: policy.Policy, line: str, rules) -> List[str]:
     """Parses a file_contexts line and runs checks"""
     # skip empty/comment line
@@ -197,7 +232,8 @@
     """Do testing"""
     parser = argparse.ArgumentParser()
     parser.add_argument('--all', action='store_true', help='tests ALL aspects')
-    parser.add_argument('-f', '--file_contexts', help='output of "deapexer list -Z"')
+    parser.add_argument('-f', '--file_contexts', required=True, help='output of "deapexer list -Z"')
+    parser.add_argument('-p', '--partition', help='partition to check Treble violations')
     args = parser.parse_args()
 
     lib_path = extract_data(LIBSEPOLWRAP, work_dir)
@@ -209,6 +245,9 @@
     else:
         rules = generic_rules
 
+    if args.partition:
+        rules.append(system_vendor_rule(args.partition))
+
     errors = []
     with open(args.file_contexts, 'rt', encoding='utf-8') as file_contexts:
         for line in file_contexts:
diff --git a/tests/apex_sepolicy_tests_test.py b/tests/apex_sepolicy_tests_test.py
index 727a023..2a92aee 100644
--- a/tests/apex_sepolicy_tests_test.py
+++ b/tests/apex_sepolicy_tests_test.py
@@ -106,7 +106,7 @@
         self.assert_ok('./bin/init u:object_r:init_exec:s0')
         self.assert_ok('./bin/hw/svc u:object_r:init_exec:s0')
         self.assert_error('./bin/hw/svc u:object_r:vendor_file:s0',
-                          r"Error: .*svc: can\'t be labelled as \'vendor_file\'")
+                          r'Error: .*svc: can\'t be labelled as \'vendor_file\'')
 
 if __name__ == '__main__':
     unittest.main(verbosity=2)