Merge "Allow privapp permission allowlist in apex" am: e978ec5b07 am: 1c565d5b4b am: 9f370ba438
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1766011 Change-Id: Icfea66a1f48d1e3fde14afa89e1c6313da01dacc
This commit is contained in:
committed by
Automerger Merge Worker
commit
ad82eb4ea3
@@ -56,6 +56,7 @@ import java.io.File;
|
|||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileReader;
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -95,6 +96,9 @@ public class SystemConfig {
|
|||||||
// property for runtime configuration differentiation in vendor
|
// property for runtime configuration differentiation in vendor
|
||||||
private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku";
|
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.
|
// Group-ids that are given to all packages as read from etc/permissions/*.xml.
|
||||||
int[] mGlobalGids = EmptyArray.INT;
|
int[] mGlobalGids = EmptyArray.INT;
|
||||||
|
|
||||||
@@ -224,6 +228,11 @@ public class SystemConfig {
|
|||||||
final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
|
final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppPermissions = new ArrayMap<>();
|
||||||
final ArrayMap<String, ArraySet<String>> mSystemExtPrivAppDenyPermissions = 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<>();
|
final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
|
||||||
|
|
||||||
// Allowed associations between applications. If there are any entries
|
// Allowed associations between applications. If there are any entries
|
||||||
@@ -360,6 +369,18 @@ public class SystemConfig {
|
|||||||
return mPrivAppDenyPermissions.get(packageName);
|
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) {
|
public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
|
||||||
return mVendorPrivAppPermissions.get(packageName);
|
return mVendorPrivAppPermissions.get(packageName);
|
||||||
}
|
}
|
||||||
@@ -573,8 +594,8 @@ public class SystemConfig {
|
|||||||
if (!isSystemProcess()) {
|
if (!isSystemProcess()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Read configuration of features and libs from apex module.
|
// Read configuration of features, libs and priv-app permissions from apex module.
|
||||||
int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES;
|
int apexPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS;
|
||||||
// TODO: Use a solid way to filter apex module folders?
|
// TODO: Use a solid way to filter apex module folders?
|
||||||
for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) {
|
for (File f: FileUtils.listFilesOrEmpty(Environment.getApexDirectory())) {
|
||||||
if (f.isFile() || f.getPath().contains("@")) {
|
if (f.isFile() || f.getPath().contains("@")) {
|
||||||
@@ -1040,10 +1061,10 @@ public class SystemConfig {
|
|||||||
} break;
|
} break;
|
||||||
case "privapp-permissions": {
|
case "privapp-permissions": {
|
||||||
if (allowPrivappPermissions) {
|
if (allowPrivappPermissions) {
|
||||||
// privapp permissions from system, vendor, product and system_ext
|
// privapp permissions from system, apex, vendor, product and
|
||||||
// partitions are stored separately. This is to prevent xml files in
|
// system_ext partitions are stored separately. This is to
|
||||||
// the vendor partition from granting permissions to priv apps in the
|
// prevent xml files in the vendor partition from granting
|
||||||
// system partition and vice versa.
|
// permissions to priv apps in the system partition and vice versa.
|
||||||
boolean vendor = permFile.toPath().startsWith(
|
boolean vendor = permFile.toPath().startsWith(
|
||||||
Environment.getVendorDirectory().toPath() + "/")
|
Environment.getVendorDirectory().toPath() + "/")
|
||||||
|| permFile.toPath().startsWith(
|
|| permFile.toPath().startsWith(
|
||||||
@@ -1052,6 +1073,8 @@ public class SystemConfig {
|
|||||||
Environment.getProductDirectory().toPath() + "/");
|
Environment.getProductDirectory().toPath() + "/");
|
||||||
boolean systemExt = permFile.toPath().startsWith(
|
boolean systemExt = permFile.toPath().startsWith(
|
||||||
Environment.getSystemExtDirectory().toPath() + "/");
|
Environment.getSystemExtDirectory().toPath() + "/");
|
||||||
|
boolean apex = permFile.toPath().startsWith(
|
||||||
|
Environment.getApexDirectory().toPath() + "/");
|
||||||
if (vendor) {
|
if (vendor) {
|
||||||
readPrivAppPermissions(parser, mVendorPrivAppPermissions,
|
readPrivAppPermissions(parser, mVendorPrivAppPermissions,
|
||||||
mVendorPrivAppDenyPermissions);
|
mVendorPrivAppDenyPermissions);
|
||||||
@@ -1061,6 +1084,8 @@ public class SystemConfig {
|
|||||||
} else if (systemExt) {
|
} else if (systemExt) {
|
||||||
readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
|
readPrivAppPermissions(parser, mSystemExtPrivAppPermissions,
|
||||||
mSystemExtPrivAppDenyPermissions);
|
mSystemExtPrivAppDenyPermissions);
|
||||||
|
} else if (apex) {
|
||||||
|
readApexPrivAppPermissions(parser, permFile);
|
||||||
} else {
|
} else {
|
||||||
readPrivAppPermissions(parser, mPrivAppPermissions,
|
readPrivAppPermissions(parser, mPrivAppPermissions,
|
||||||
mPrivAppDenyPermissions);
|
mPrivAppDenyPermissions);
|
||||||
@@ -1616,6 +1641,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() {
|
private static boolean isSystemProcess() {
|
||||||
return Process.myUid() == Process.SYSTEM_UID;
|
return Process.myUid() == Process.SYSTEM_UID;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2438,6 +2438,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() {
|
private int runGetPrivappPermissions() {
|
||||||
final String pkg = getNextArg();
|
final String pkg = getNextArg();
|
||||||
if (pkg == null) {
|
if (pkg == null) {
|
||||||
@@ -2453,6 +2462,9 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
} else if (isSystemExtApp(pkg)) {
|
} else if (isSystemExtApp(pkg)) {
|
||||||
privAppPermissions = SystemConfig.getInstance()
|
privAppPermissions = SystemConfig.getInstance()
|
||||||
.getSystemExtPrivAppPermissions(pkg);
|
.getSystemExtPrivAppPermissions(pkg);
|
||||||
|
} else if (isApexApp(pkg)) {
|
||||||
|
privAppPermissions = SystemConfig.getInstance()
|
||||||
|
.getApexPrivAppPermissions(getApexPackageNameContainingPackage(pkg), pkg);
|
||||||
} else {
|
} else {
|
||||||
privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
|
privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
|
||||||
}
|
}
|
||||||
@@ -2477,6 +2489,9 @@ class PackageManagerShellCommand extends ShellCommand {
|
|||||||
} else if (isSystemExtApp(pkg)) {
|
} else if (isSystemExtApp(pkg)) {
|
||||||
privAppPermissions = SystemConfig.getInstance()
|
privAppPermissions = SystemConfig.getInstance()
|
||||||
.getSystemExtPrivAppDenyPermissions(pkg);
|
.getSystemExtPrivAppDenyPermissions(pkg);
|
||||||
|
} else if (isApexApp(pkg)) {
|
||||||
|
privAppPermissions = SystemConfig.getInstance()
|
||||||
|
.getApexPrivAppDenyPermissions(getApexPackageNameContainingPackage(pkg), pkg);
|
||||||
} else {
|
} else {
|
||||||
privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
|
privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3454,10 +3454,15 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
final String permissionName = permission.getName();
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName)) {
|
if (isInSystemConfigPrivAppDenyPermissions(pkg, permissionName,
|
||||||
|
containingApexPackageName)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Updated system apps do not need to be allowlisted
|
// Updated system apps do not need to be allowlisted
|
||||||
@@ -3474,9 +3479,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
|||||||
}
|
}
|
||||||
// Only enforce the allowlist on boot
|
// Only enforce the allowlist on boot
|
||||||
if (!mSystemReady) {
|
if (!mSystemReady) {
|
||||||
final ApexManager apexManager = ApexManager.getInstance();
|
|
||||||
final String containingApexPackageName =
|
|
||||||
apexManager.getActiveApexPackageNameContainingPackage(packageName);
|
|
||||||
final boolean isInUpdatedApex = containingApexPackageName != null
|
final boolean isInUpdatedApex = containingApexPackageName != null
|
||||||
&& !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName,
|
&& !apexManager.isFactory(apexManager.getPackageInfo(containingApexPackageName,
|
||||||
MATCH_ACTIVE_PACKAGE));
|
MATCH_ACTIVE_PACKAGE));
|
||||||
@@ -3500,7 +3502,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInSystemConfigPrivAppPermissions(@NonNull AndroidPackage pkg,
|
private boolean isInSystemConfigPrivAppPermissions(@NonNull AndroidPackage pkg,
|
||||||
@NonNull String permission) {
|
@NonNull String permission, String containingApexPackageName) {
|
||||||
final SystemConfig systemConfig = SystemConfig.getInstance();
|
final SystemConfig systemConfig = SystemConfig.getInstance();
|
||||||
final Set<String> permissions;
|
final Set<String> permissions;
|
||||||
if (pkg.isVendor()) {
|
if (pkg.isVendor()) {
|
||||||
@@ -3509,6 +3511,26 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
|||||||
permissions = systemConfig.getProductPrivAppPermissions(pkg.getPackageName());
|
permissions = systemConfig.getProductPrivAppPermissions(pkg.getPackageName());
|
||||||
} else if (pkg.isSystemExt()) {
|
} else if (pkg.isSystemExt()) {
|
||||||
permissions = systemConfig.getSystemExtPrivAppPermissions(pkg.getPackageName());
|
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 {
|
} else {
|
||||||
permissions = systemConfig.getPrivAppPermissions(pkg.getPackageName());
|
permissions = systemConfig.getPrivAppPermissions(pkg.getPackageName());
|
||||||
}
|
}
|
||||||
@@ -3516,7 +3538,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isInSystemConfigPrivAppDenyPermissions(@NonNull AndroidPackage pkg,
|
private boolean isInSystemConfigPrivAppDenyPermissions(@NonNull AndroidPackage pkg,
|
||||||
@NonNull String permission) {
|
@NonNull String permission, String containingApexPackageName) {
|
||||||
final SystemConfig systemConfig = SystemConfig.getInstance();
|
final SystemConfig systemConfig = SystemConfig.getInstance();
|
||||||
final Set<String> permissions;
|
final Set<String> permissions;
|
||||||
if (pkg.isVendor()) {
|
if (pkg.isVendor()) {
|
||||||
@@ -3525,6 +3547,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|
|||||||
permissions = systemConfig.getProductPrivAppDenyPermissions(pkg.getPackageName());
|
permissions = systemConfig.getProductPrivAppDenyPermissions(pkg.getPackageName());
|
||||||
} else if (pkg.isSystemExt()) {
|
} else if (pkg.isSystemExt()) {
|
||||||
permissions = systemConfig.getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
|
permissions = systemConfig.getSystemExtPrivAppDenyPermissions(pkg.getPackageName());
|
||||||
|
} else if (containingApexPackageName != null) {
|
||||||
|
permissions = systemConfig.getApexPrivAppDenyPermissions(containingApexPackageName,
|
||||||
|
pkg.getPackageName());
|
||||||
} else {
|
} else {
|
||||||
permissions = systemConfig.getPrivAppDenyPermissions(pkg.getPackageName());
|
permissions = systemConfig.getPrivAppDenyPermissions(pkg.getPackageName());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user