Loading core/java/com/android/server/SystemConfig.java +68 −6 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; Loading Loading @@ -95,6 +96,9 @@ public class SystemConfig { // property for runtime configuration differentiation in vendor private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku"; private static final ArrayMap<String, ArraySet<String>> EMPTY_PERMISSIONS = new ArrayMap<>(); // Group-ids that are given to all packages as read from etc/permissions/*.xml. int[] mGlobalGids = EmptyArray.INT; Loading Loading @@ -281,6 +285,11 @@ public class SystemConfig { final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>(); final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>(); final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppPermissions = new ArrayMap<>(); final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppDenyPermissions = new ArrayMap<>(); final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>(); // Allowed associations between applications. If there are any entries Loading Loading @@ -417,6 +426,18 @@ public class SystemConfig { return mPrivAppDenyPermissions.get(packageName); } /** Get privapp permission allowlist for an apk-in-apex. */ public ArraySet<String> getApexPrivAppPermissions(String module, String packageName) { return mApexPrivAppPermissions.getOrDefault(module, EMPTY_PERMISSIONS) .get(packageName); } /** Get privapp permissions denylist for an apk-in-apex. */ public ArraySet<String> getApexPrivAppDenyPermissions(String module, String packageName) { return mApexPrivAppDenyPermissions.getOrDefault(module, EMPTY_PERMISSIONS) .get(packageName); } public ArraySet<String> getVendorPrivAppPermissions(String packageName) { return mVendorPrivAppPermissions.get(packageName); } Loading Loading @@ -632,8 +653,8 @@ public class SystemConfig { if (!isSystemProcess()) { return; } // Read configuration of features and libs from apex module. int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES; // Read configuration of features, libs and priv-app permissions from apex module. int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS; // TODO: Use a solid way to filter apex module folders? for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) { if (f.isFile() || f.getPath().contains("@")) { Loading Loading @@ -1116,10 +1137,10 @@ public class SystemConfig { } break; case "privapp-permissions": { if (allowPrivappPermissions) { // privapp permissions from system, vendor, product and system_ext // partitions are stored separately. This is to prevent xml files in // the vendor partition from granting permissions to priv apps in the // system partition and vice versa. // privapp permissions from system, apex, vendor, product and // system_ext partitions are stored separately. This is to // prevent xml files in the vendor partition from granting // permissions to priv apps in the system partition and vice versa. boolean vendor = permFile.toPath().startsWith( Environment.getVendorDirectory().toPath() + "/") || permFile.toPath().startsWith( Loading @@ -1128,6 +1149,8 @@ public class SystemConfig { Environment.getProductDirectory().toPath() + "/"); boolean systemExt = permFile.toPath().startsWith( Environment.getSystemExtDirectory().toPath() + "/"); boolean apex = permFile.toPath().startsWith( Environment.getApexDirectory().toPath() + "/"); if (vendor) { readPrivAppPermissions(parser, mVendorPrivAppPermissions, mVendorPrivAppDenyPermissions); Loading @@ -1137,6 +1160,8 @@ public class SystemConfig { } else if (systemExt) { readPrivAppPermissions(parser, mSystemExtPrivAppPermissions, mSystemExtPrivAppDenyPermissions); } else if (apex) { readApexPrivAppPermissions(parser, permFile); } else { readPrivAppPermissions(parser, mPrivAppPermissions, mPrivAppDenyPermissions); Loading Loading @@ -1692,6 +1717,43 @@ public class SystemConfig { } } /** * Returns the module name for a file in the apex module's partition. */ private String getApexModuleNameFromFilePath(Path path) { final Path apexDirectoryPath = Environment.getApexDirectory().toPath(); if (!path.startsWith(apexDirectoryPath)) { throw new IllegalArgumentException("File " + path + " is not part of an APEX."); } // File must be in <apex_directory>/<module_name>/[extra_paths/]<xml_file> if (path.getNameCount() <= (apexDirectoryPath.getNameCount() + 1)) { throw new IllegalArgumentException("File " + path + " is in the APEX partition," + " but not inside a module."); } return path.getName(apexDirectoryPath.getNameCount()).toString(); } private void readApexPrivAppPermissions(XmlPullParser parser, File permFile) throws IOException, XmlPullParserException { final String moduleName = getApexModuleNameFromFilePath(permFile.toPath()); final ArrayMap<String, ArraySet<String>> privAppPermissions; if (mApexPrivAppPermissions.containsKey(moduleName)) { privAppPermissions = mApexPrivAppPermissions.get(moduleName); } else { privAppPermissions = new ArrayMap<>(); mApexPrivAppPermissions.put(moduleName, privAppPermissions); } final ArrayMap<String, ArraySet<String>> privAppDenyPermissions; if (mApexPrivAppDenyPermissions.containsKey(moduleName)) { privAppDenyPermissions = mApexPrivAppDenyPermissions.get(moduleName); } else { privAppDenyPermissions = new ArrayMap<>(); mApexPrivAppDenyPermissions.put(moduleName, privAppDenyPermissions); } readPrivAppPermissions(parser, privAppPermissions, privAppDenyPermissions); } private static boolean isSystemProcess() { return Process.myUid() == Process.SYSTEM_UID; } Loading services/core/java/com/android/server/pm/PackageManagerShellCommand.java +15 −0 Original line number Diff line number Diff line Loading @@ -2487,6 +2487,15 @@ class PackageManagerShellCommand extends ShellCommand { } } private String getApexPackageNameContainingPackage(String pkg) { ApexManager apexManager = ApexManager.getInstance(); return apexManager.getActiveApexPackageNameContainingPackage(pkg); } private boolean isApexApp(String pkg) { return getApexPackageNameContainingPackage(pkg) != null; } private int runGetPrivappPermissions() { final String pkg = getNextArg(); if (pkg == null) { Loading @@ -2502,6 +2511,9 @@ class PackageManagerShellCommand extends ShellCommand { } else if (isSystemExtApp(pkg)) { privAppPermissions = SystemConfig.getInstance() .getSystemExtPrivAppPermissions(pkg); } else if (isApexApp(pkg)) { privAppPermissions = SystemConfig.getInstance() .getApexPrivAppPermissions(getApexPackageNameContainingPackage(pkg), pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); } Loading @@ -2526,6 +2538,9 @@ class PackageManagerShellCommand extends ShellCommand { } else if (isSystemExtApp(pkg)) { privAppPermissions = SystemConfig.getInstance() .getSystemExtPrivAppDenyPermissions(pkg); } else if (isApexApp(pkg)) { privAppPermissions = SystemConfig.getInstance() .getApexPrivAppDenyPermissions(getApexPackageNameContainingPackage(pkg), pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); } Loading services/core/java/com/android/server/pm/permission/PermissionManagerService.java +32 −7 Original line number Diff line number Diff line Loading @@ -3484,10 +3484,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { return true; } final String permissionName = permission.getName(); if (isInSystemConfigPrivAppPermissions(pkg, permissionName)) { final ApexManager apexManager = ApexManager.getInstance(); final String containingApexPackageName = apexManager.getActiveApexPackageNameContainingPackage(packageName); if (isInSystemConfigPrivAppPermissions(pkg, permissionName, containingApexPackageName)) { return true; } if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName)) { if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName, containingApexPackageName)) { return false; } // Updated system apps do not need to be allowlisted Loading @@ -3504,9 +3509,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { } // Only enforce the allowlist on boot if (!mSystemReady) { final ApexManager apexManager = ApexManager.getInstance(); final String containingApexPackageName = apexManager.getActiveApexPackageNameContainingPackage(packageName); final boolean isInUpdatedApex = containingApexPackageName != null && !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName, MATCH_ACTIVE_PACKAGE)); Loading @@ -3530,7 +3532,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } private boolean isInSystemConfigPrivAppPermissions(@NonNull AndroidPackage pkg, @NonNull String permission) { @NonNull String permission, String containingApexPackageName) { final SystemConfig systemConfig = SystemConfig.getInstance(); final Set<String> permissions; if (pkg.isVendor()) { Loading @@ -3539,6 +3541,26 @@ public class PermissionManagerService extends IPermissionManager.Stub { permissions = systemConfig.getProductPrivAppPermissions(pkg.getPackageName()); } else if (pkg.isSystemExt()) { permissions = systemConfig.getSystemExtPrivAppPermissions(pkg.getPackageName()); } else if (containingApexPackageName != null) { final Set<String> privAppPermissions = systemConfig.getPrivAppPermissions( pkg.getPackageName()); final Set<String> apexPermissions = systemConfig.getApexPrivAppPermissions( containingApexPackageName, pkg.getPackageName()); if (privAppPermissions != null) { // TODO(andreionea): Remove check as soon as all apk-in-apex // permission allowlists are migrated. Slog.w(TAG, "Package " + pkg.getPackageName() + " is an APK in APEX," + " but has permission allowlist on the system image. Please bundle the" + " allowlist in the " + containingApexPackageName + " APEX instead."); if (apexPermissions != null) { permissions = new ArraySet<>(privAppPermissions); permissions.addAll(apexPermissions); } else { permissions = privAppPermissions; } } else { permissions = apexPermissions; } } else { permissions = systemConfig.getPrivAppPermissions(pkg.getPackageName()); } Loading @@ -3546,7 +3568,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } private boolean isInSystemConfigPrivAppDenyPermissions(@NonNull AndroidPackage pkg, @NonNull String permission) { @NonNull String permission, String containingApexPackageName) { final SystemConfig systemConfig = SystemConfig.getInstance(); final Set<String> permissions; if (pkg.isVendor()) { Loading @@ -3555,6 +3577,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { permissions = systemConfig.getProductPrivAppDenyPermissions(pkg.getPackageName()); } else if (pkg.isSystemExt()) { permissions = systemConfig.getSystemExtPrivAppDenyPermissions(pkg.getPackageName()); } else if (containingApexPackageName != null) { permissions = systemConfig.getApexPrivAppDenyPermissions(containingApexPackageName, pkg.getPackageName()); } else { permissions = systemConfig.getPrivAppDenyPermissions(pkg.getPackageName()); } Loading Loading
core/java/com/android/server/SystemConfig.java +68 −6 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; import java.util.List; Loading Loading @@ -95,6 +96,9 @@ public class SystemConfig { // property for runtime configuration differentiation in vendor private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku"; private static final ArrayMap<String, ArraySet<String>> EMPTY_PERMISSIONS = new ArrayMap<>(); // Group-ids that are given to all packages as read from etc/permissions/*.xml. int[] mGlobalGids = EmptyArray.INT; Loading Loading @@ -281,6 +285,11 @@ public class SystemConfig { final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>(); final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = new ArrayMap<>(); final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppPermissions = new ArrayMap<>(); final ArrayMap<String, ArrayMap<String, ArraySet<String>>> mApexPrivAppDenyPermissions = new ArrayMap<>(); final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>(); // Allowed associations between applications. If there are any entries Loading Loading @@ -417,6 +426,18 @@ public class SystemConfig { return mPrivAppDenyPermissions.get(packageName); } /** Get privapp permission allowlist for an apk-in-apex. */ public ArraySet<String> getApexPrivAppPermissions(String module, String packageName) { return mApexPrivAppPermissions.getOrDefault(module, EMPTY_PERMISSIONS) .get(packageName); } /** Get privapp permissions denylist for an apk-in-apex. */ public ArraySet<String> getApexPrivAppDenyPermissions(String module, String packageName) { return mApexPrivAppDenyPermissions.getOrDefault(module, EMPTY_PERMISSIONS) .get(packageName); } public ArraySet<String> getVendorPrivAppPermissions(String packageName) { return mVendorPrivAppPermissions.get(packageName); } Loading Loading @@ -632,8 +653,8 @@ public class SystemConfig { if (!isSystemProcess()) { return; } // Read configuration of features and libs from apex module. int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES; // Read configuration of features, libs and priv-app permissions from apex module. int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS; // TODO: Use a solid way to filter apex module folders? for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) { if (f.isFile() || f.getPath().contains("@")) { Loading Loading @@ -1116,10 +1137,10 @@ public class SystemConfig { } break; case "privapp-permissions": { if (allowPrivappPermissions) { // privapp permissions from system, vendor, product and system_ext // partitions are stored separately. This is to prevent xml files in // the vendor partition from granting permissions to priv apps in the // system partition and vice versa. // privapp permissions from system, apex, vendor, product and // system_ext partitions are stored separately. This is to // prevent xml files in the vendor partition from granting // permissions to priv apps in the system partition and vice versa. boolean vendor = permFile.toPath().startsWith( Environment.getVendorDirectory().toPath() + "/") || permFile.toPath().startsWith( Loading @@ -1128,6 +1149,8 @@ public class SystemConfig { Environment.getProductDirectory().toPath() + "/"); boolean systemExt = permFile.toPath().startsWith( Environment.getSystemExtDirectory().toPath() + "/"); boolean apex = permFile.toPath().startsWith( Environment.getApexDirectory().toPath() + "/"); if (vendor) { readPrivAppPermissions(parser, mVendorPrivAppPermissions, mVendorPrivAppDenyPermissions); Loading @@ -1137,6 +1160,8 @@ public class SystemConfig { } else if (systemExt) { readPrivAppPermissions(parser, mSystemExtPrivAppPermissions, mSystemExtPrivAppDenyPermissions); } else if (apex) { readApexPrivAppPermissions(parser, permFile); } else { readPrivAppPermissions(parser, mPrivAppPermissions, mPrivAppDenyPermissions); Loading Loading @@ -1692,6 +1717,43 @@ public class SystemConfig { } } /** * Returns the module name for a file in the apex module's partition. */ private String getApexModuleNameFromFilePath(Path path) { final Path apexDirectoryPath = Environment.getApexDirectory().toPath(); if (!path.startsWith(apexDirectoryPath)) { throw new IllegalArgumentException("File " + path + " is not part of an APEX."); } // File must be in <apex_directory>/<module_name>/[extra_paths/]<xml_file> if (path.getNameCount() <= (apexDirectoryPath.getNameCount() + 1)) { throw new IllegalArgumentException("File " + path + " is in the APEX partition," + " but not inside a module."); } return path.getName(apexDirectoryPath.getNameCount()).toString(); } private void readApexPrivAppPermissions(XmlPullParser parser, File permFile) throws IOException, XmlPullParserException { final String moduleName = getApexModuleNameFromFilePath(permFile.toPath()); final ArrayMap<String, ArraySet<String>> privAppPermissions; if (mApexPrivAppPermissions.containsKey(moduleName)) { privAppPermissions = mApexPrivAppPermissions.get(moduleName); } else { privAppPermissions = new ArrayMap<>(); mApexPrivAppPermissions.put(moduleName, privAppPermissions); } final ArrayMap<String, ArraySet<String>> privAppDenyPermissions; if (mApexPrivAppDenyPermissions.containsKey(moduleName)) { privAppDenyPermissions = mApexPrivAppDenyPermissions.get(moduleName); } else { privAppDenyPermissions = new ArrayMap<>(); mApexPrivAppDenyPermissions.put(moduleName, privAppDenyPermissions); } readPrivAppPermissions(parser, privAppPermissions, privAppDenyPermissions); } private static boolean isSystemProcess() { return Process.myUid() == Process.SYSTEM_UID; } Loading
services/core/java/com/android/server/pm/PackageManagerShellCommand.java +15 −0 Original line number Diff line number Diff line Loading @@ -2487,6 +2487,15 @@ class PackageManagerShellCommand extends ShellCommand { } } private String getApexPackageNameContainingPackage(String pkg) { ApexManager apexManager = ApexManager.getInstance(); return apexManager.getActiveApexPackageNameContainingPackage(pkg); } private boolean isApexApp(String pkg) { return getApexPackageNameContainingPackage(pkg) != null; } private int runGetPrivappPermissions() { final String pkg = getNextArg(); if (pkg == null) { Loading @@ -2502,6 +2511,9 @@ class PackageManagerShellCommand extends ShellCommand { } else if (isSystemExtApp(pkg)) { privAppPermissions = SystemConfig.getInstance() .getSystemExtPrivAppPermissions(pkg); } else if (isApexApp(pkg)) { privAppPermissions = SystemConfig.getInstance() .getApexPrivAppPermissions(getApexPackageNameContainingPackage(pkg), pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); } Loading @@ -2526,6 +2538,9 @@ class PackageManagerShellCommand extends ShellCommand { } else if (isSystemExtApp(pkg)) { privAppPermissions = SystemConfig.getInstance() .getSystemExtPrivAppDenyPermissions(pkg); } else if (isApexApp(pkg)) { privAppPermissions = SystemConfig.getInstance() .getApexPrivAppDenyPermissions(getApexPackageNameContainingPackage(pkg), pkg); } else { privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); } Loading
services/core/java/com/android/server/pm/permission/PermissionManagerService.java +32 −7 Original line number Diff line number Diff line Loading @@ -3484,10 +3484,15 @@ public class PermissionManagerService extends IPermissionManager.Stub { return true; } final String permissionName = permission.getName(); if (isInSystemConfigPrivAppPermissions(pkg, permissionName)) { final ApexManager apexManager = ApexManager.getInstance(); final String containingApexPackageName = apexManager.getActiveApexPackageNameContainingPackage(packageName); if (isInSystemConfigPrivAppPermissions(pkg, permissionName, containingApexPackageName)) { return true; } if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName)) { if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName, containingApexPackageName)) { return false; } // Updated system apps do not need to be allowlisted Loading @@ -3504,9 +3509,6 @@ public class PermissionManagerService extends IPermissionManager.Stub { } // Only enforce the allowlist on boot if (!mSystemReady) { final ApexManager apexManager = ApexManager.getInstance(); final String containingApexPackageName = apexManager.getActiveApexPackageNameContainingPackage(packageName); final boolean isInUpdatedApex = containingApexPackageName != null && !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName, MATCH_ACTIVE_PACKAGE)); Loading @@ -3530,7 +3532,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } private boolean isInSystemConfigPrivAppPermissions(@NonNull AndroidPackage pkg, @NonNull String permission) { @NonNull String permission, String containingApexPackageName) { final SystemConfig systemConfig = SystemConfig.getInstance(); final Set<String> permissions; if (pkg.isVendor()) { Loading @@ -3539,6 +3541,26 @@ public class PermissionManagerService extends IPermissionManager.Stub { permissions = systemConfig.getProductPrivAppPermissions(pkg.getPackageName()); } else if (pkg.isSystemExt()) { permissions = systemConfig.getSystemExtPrivAppPermissions(pkg.getPackageName()); } else if (containingApexPackageName != null) { final Set<String> privAppPermissions = systemConfig.getPrivAppPermissions( pkg.getPackageName()); final Set<String> apexPermissions = systemConfig.getApexPrivAppPermissions( containingApexPackageName, pkg.getPackageName()); if (privAppPermissions != null) { // TODO(andreionea): Remove check as soon as all apk-in-apex // permission allowlists are migrated. Slog.w(TAG, "Package " + pkg.getPackageName() + " is an APK in APEX," + " but has permission allowlist on the system image. Please bundle the" + " allowlist in the " + containingApexPackageName + " APEX instead."); if (apexPermissions != null) { permissions = new ArraySet<>(privAppPermissions); permissions.addAll(apexPermissions); } else { permissions = privAppPermissions; } } else { permissions = apexPermissions; } } else { permissions = systemConfig.getPrivAppPermissions(pkg.getPackageName()); } Loading @@ -3546,7 +3568,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } private boolean isInSystemConfigPrivAppDenyPermissions(@NonNull AndroidPackage pkg, @NonNull String permission) { @NonNull String permission, String containingApexPackageName) { final SystemConfig systemConfig = SystemConfig.getInstance(); final Set<String> permissions; if (pkg.isVendor()) { Loading @@ -3555,6 +3577,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { permissions = systemConfig.getProductPrivAppDenyPermissions(pkg.getPackageName()); } else if (pkg.isSystemExt()) { permissions = systemConfig.getSystemExtPrivAppDenyPermissions(pkg.getPackageName()); } else if (containingApexPackageName != null) { permissions = systemConfig.getApexPrivAppDenyPermissions(containingApexPackageName, pkg.getPackageName()); } else { permissions = systemConfig.getPrivAppDenyPermissions(pkg.getPackageName()); } Loading