Snap for 13605992 from b5393e7783a0774ae4c4166f7cc51e2eeeccef4d to 25Q3-release

Change-Id: I2f3d4ccb829be7d66fa8d9a92521f6ac86e33104
diff --git a/private/attributes b/private/attributes
index af4f60b..9efa83c 100644
--- a/private/attributes
+++ b/private/attributes
@@ -22,3 +22,8 @@
 # WARNING: USING THE update_provider ATTRIBUTE WILL CAUSE CTS TO FAIL!
 attribute update_provider;
 expandattribute update_provider false;
+
+until_board_api(202604, `
+attribute treble_labeling_violators;
+expandattribute treble_labeling_violators false;
+')
diff --git a/public/attributes b/public/attributes
index 0ce494c..5cf994c 100644
--- a/public/attributes
+++ b/public/attributes
@@ -465,3 +465,10 @@
 
 # HAL service used for custom smc filtering project
 hal_attribute(vm_capabilities);
+
+# Domains violating Treble Labeling
+# debuggable builds ONLY. NOT ALLOWED on user builds.
+starting_at_board_api(202604, `
+attribute treble_labeling_violators;
+expandattribute treble_labeling_violators false;
+')
diff --git a/tests/treble_labeling_tests.md b/tests/treble_labeling_tests.md
index 8f78f09..dbbce02 100644
--- a/tests/treble_labeling_tests.md
+++ b/tests/treble_labeling_tests.md
@@ -146,12 +146,18 @@
 platform_apps_in_vendor_seapp_contexts:
   - apk: SomePlatformApp.apk # name of APK
     bug: 112233445
+  - name: com.android.platform.app # or name of the package
+    bug: 554433221
 non_coredomain_for_platform_apps:
   - apk: SomeNonCoredomainApp.apk # name of APK
     bug: 112233445
+  - name: com.android.noncoredomain # or name of the package
+    bug: 554433221
 coredomain_for_vendor_apps:
   - apk: VendorServiceA.apk # name of APK
     bug: 314159265
+  - name: vendor.companya.servicea # or name of the package
+    bug: 358979323
 ```
 
 If no such violations are currently allowed, lists can be empty like:
@@ -167,3 +173,24 @@
 PRODUCT_SELINUX_TREBLE_LABELING_TRACKING_LIST_FILE := \
     device/google/your-device/sepolicy/tracking_list.yaml
 ```
+
+## `treble_labeling_violators`: Exemption for debuggable-only apps
+
+Some debuggable-only (`PRODUCT_PACKAGES_DEBUG`) apps require more permissions
+than the Treble enforcement. For example, an app installed to `system_ext` may
+need to dump vendor-specific resources. It doesn't make sense to enforce such
+debuggable-only apps, because the apps are never meant to be released.
+
+`treble_labeling_violators` is an attribute to exempt debuggable-only apps.
+Adding `treble_labeling_violators` to domain types will make the tests skip apps
+labeled with such types. The attribute is only for debuggable builds, and using
+the attribute on user builds will cause a build error.
+
+```
+type ramdump_app, domain;
+
+userdebug_or_eng(`
+    # Apps labeled as ramdump_app will be exempted from the labeling tests.
+    typeattributeset ramdump_app treble_labeling_violators;
+')
+```
diff --git a/tests/treble_labeling_tests.py b/tests/treble_labeling_tests.py
index 9c49a34..0e728ff 100644
--- a/tests/treble_labeling_tests.py
+++ b/tests/treble_labeling_tests.py
@@ -121,9 +121,16 @@
         help="Treat test failures as warnings instead of errors.",
         required=False,
     )
+    parser.add_argument(
+        "--debuggable",
+        action="store_true",
+        help="Exempt treble_labeling_violators from tests.",
+        required=False,
+    )
     return parser
 
-def TestNoCoredomainInVendorSepolicy(pol_without_vendor, pol, allowlist):
+def TestNoCoredomainInVendorSepolicy(pol_without_vendor, pol, allowlist,
+                                     exempted_types):
     """Tests if vendor SEPolicy adds more coredomain types.
     coredomain is only for platform types, so vendor SEPolicy must not add one.
     """
@@ -133,6 +140,7 @@
 
     allowed_types = {entry["domain"] for entry in allowlist}
     violations = coredomain_types - platform_coredomain_types - allowed_types
+    violations -= exempted_types
 
     if violations:
         return ("ERROR: The attribute 'coredomain' is only for platform "
@@ -277,7 +285,8 @@
 
 def TestNoPlatformAppsInVendorSeappContexts(platform_apps,
                                             vendor_seapp_entries,
-                                            allowlist):
+                                            allowlist,
+                                            exempted_types):
     """Tests if vendor SEPolicy labels any of preinstalled platform apps.
     Platform apps can't be labeled with vendor SEPolicy. Also vendor's
     seapp_contexts must use 'name=' condition, because vendor's seapp_contexts
@@ -286,7 +295,8 @@
     no_name_violations = []
     partition_violations = []
 
-    allowed_apks = {entry["apk"] for entry in allowlist}
+    allowed_apks = {entry["apk"] for entry in allowlist if "apk" in entry}
+    allowed_names = {entry["name"] for entry in allowlist if "name" in entry}
 
     for entry in vendor_seapp_entries:
         values = entry.values
@@ -294,11 +304,15 @@
         if "name" not in values or not values["name"]:
             no_name_violations.append((entry.partition, values["_raw"]))
             continue
+        if values["domain"] in exempted_types:
+            continue
 
         # Such name patterns must not match with platform_apps
         for app in platform_apps:
             if app.apk_name in allowed_apks:
                 continue
+            if app.package_name in allowed_names:
+                continue
             if package_name_match(app.package_name, values["name"]):
                 partition_violations.append((app.apk_name, app.package_name,
                                              entry.partition, values["_raw"]))
@@ -337,7 +351,7 @@
     return result
 
 def TestCoredomainForAllPlatformApps(platform_apps, platform_seapp_entries,
-                                     pol, allowlist):
+                                     pol, allowlist, exempted_types):
     """Tests if platform SEPolicy labels any of preinstalled platform apps with
     a non-coredomain label. All preinstalled platform apps are expected to be
     labeled with a coredomain type.
@@ -345,16 +359,21 @@
     coredomains = pol.QueryTypeAttribute("coredomain", True)
     violations = []
 
-    allowed_apks = {entry["apk"] for entry in allowlist}
+    allowed_apks = {entry["apk"] for entry in allowlist if "apk" in entry}
+    allowed_names = {entry["name"] for entry in allowlist if "name" in entry}
 
     for entry in platform_seapp_entries:
         values = entry.values
         if not values["name"] or values["domain"] in coredomains:
             continue
+        if values["domain"] in exempted_types:
+            continue
 
         for app in platform_apps:
             if app.apk_name in allowed_apks:
                 continue
+            if app.package_name in allowed_names:
+                continue
             if package_name_match(app.package_name, values["name"]):
                 violations.append((app.apk_name, app.package_name,
                                    values["domain"]))
@@ -378,23 +397,28 @@
     return ""
 
 def TestNoCoredomainForAllVendorApps(vendor_apps, seapp_entries, pol,
-                                     allowlist):
+                                     allowlist, exempted_types):
     """Tests if any of preinstalled vendor apps are labeled with coredomain
     labels. All preinstalled vendor apps are expected to be non-coredomain.
     """
     coredomains = pol.QueryTypeAttribute("coredomain", True)
     violations = []
 
-    allowed_apks = {entry["apk"] for entry in allowlist}
+    allowed_apks = {entry["apk"] for entry in allowlist if "apk" in entry}
+    allowed_names = {entry["name"] for entry in allowlist if "name" in entry}
 
     for entry in seapp_entries:
         values = entry.values
         if not values["name"] or values["domain"] not in coredomains:
             continue
+        if values["domain"] in exempted_types:
+            continue
 
         for app in vendor_apps:
             if app.apk_name in allowed_apks:
                 continue
+            if app.package_name in allowed_names:
+                continue
             if package_name_match(app.package_name, values["name"]):
                 violations.append((app.apk_name, app.package_name,
                                    values["domain"]))
@@ -440,32 +464,45 @@
 
     seapp_entries = platform_seapp_entries + vendor_seapp_entries
 
+    exempted_types = pol.QueryTypeAttribute("treble_labeling_violators", True)
+
     result = ""
+
+    if not args.debuggable:
+        if exempted_types:
+            sys.exit("treble_labeling_violators can't be used on user builds.\n"
+                     "Please guard it with userdebug_or_eng macro.\n"
+                    f"violators:\n{exempted_types}\n")
+
     result += TestNoCoredomainInVendorSepolicy(
         pol_without_vendor,
         pol,
-        tracking_list.get('coredomain_in_vendor', [])
+        tracking_list.get('coredomain_in_vendor', []),
+        exempted_types
     )
     result += TestNoPlatformFilesInVendorFileContexts(
         args.vendor_file_contexts,
-        tracking_list.get('platform_file_in_vendor_file_contexts', [])
+        tracking_list.get('platform_file_in_vendor_file_contexts', []),
     )
     result += TestNoPlatformAppsInVendorSeappContexts(
         platform_apps,
         vendor_seapp_entries,
-        tracking_list.get('platform_apps_in_vendor_seapp_contexts', [])
+        tracking_list.get('platform_apps_in_vendor_seapp_contexts', []),
+        exempted_types
     )
     result += TestCoredomainForAllPlatformApps(
         platform_apps,
         platform_seapp_entries,
         pol,
-        tracking_list.get('non_coredomain_for_platform_apps', [])
+        tracking_list.get('non_coredomain_for_platform_apps', []),
+        exempted_types
     )
     result += TestNoCoredomainForAllVendorApps(
         vendor_apps,
         seapp_entries,
         pol,
-        tracking_list.get('coredomain_for_vendor_apps', [])
+        tracking_list.get('coredomain_for_vendor_apps', []),
+        exempted_types
     )
 
     if not result: