summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java85
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java14
2 files changed, 81 insertions, 18 deletions
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index 0c46bde4f997..c97f33b5103f 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -62,6 +62,7 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;
@@ -74,7 +75,7 @@ public abstract class ApexManager {
private static final String TAG = "ApexManager";
- static final int MATCH_ACTIVE_PACKAGE = 1 << 0;
+ public static final int MATCH_ACTIVE_PACKAGE = 1 << 0;
static final int MATCH_FACTORY_PACKAGE = 1 << 1;
private static final Singleton<ApexManager> sApexManagerSingleton =
@@ -163,7 +164,7 @@ public abstract class ApexManager {
* is not found.
*/
@Nullable
- abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags);
+ public abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags);
/**
* Retrieves information about all active APEX packages.
@@ -198,6 +199,27 @@ public abstract class ApexManager {
abstract boolean isApexPackage(String packageName);
/**
+ * Whether the APEX package is pre-installed or not.
+ *
+ * @param packageInfo the package to check
+ * @return {@code true} if this package is pre-installed, {@code false} otherwise.
+ */
+ public static boolean isFactory(@NonNull PackageInfo packageInfo) {
+ return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ }
+
+ /**
+ * Returns the active apex package's name that contains the (apk) package.
+ *
+ * @param containedPackage The (apk) package that might be in a apex
+ * @return the apex package's name of {@code null} if the {@code containedPackage} is not inside
+ * any apex.
+ */
+ @Nullable
+ public abstract String getActiveApexPackageNameContainingPackage(
+ @NonNull AndroidPackage containedPackage);
+
+ /**
* Retrieves information about an apexd staged session i.e. the internal state used by apexd to
* track the different states of a session.
*
@@ -351,7 +373,7 @@ public abstract class ApexManager {
* difference between {@code packageName} and {@code apexModuleName}.
*/
@GuardedBy("mLock")
- private Map<String, List<String>> mApksInApex = new ArrayMap<>();
+ private ArrayMap<String, List<String>> mApksInApex = new ArrayMap<>();
@GuardedBy("mLock")
private List<PackageInfo> mAllPackagesCache;
@@ -366,7 +388,7 @@ public abstract class ApexManager {
* the apk container to {@code apexModuleName} of the apex-payload inside.
*/
@GuardedBy("mLock")
- private Map<String, String> mPackageNameToApexModuleName;
+ private ArrayMap<String, String> mPackageNameToApexModuleName;
ApexManagerImpl(IApexService apexService) {
mApexService = apexService;
@@ -382,16 +404,6 @@ public abstract class ApexManager {
return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
}
- /**
- * Whether the APEX package is pre-installed or not.
- *
- * @param packageInfo the package to check
- * @return {@code true} if this package is pre-installed, {@code false} otherwise.
- */
- private static boolean isFactory(PackageInfo packageInfo) {
- return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
- }
-
@Override
public List<ActiveApexInfo> getActiveApexInfos() {
final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
@@ -503,7 +515,9 @@ public abstract class ApexManager {
}
@Override
- @Nullable PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) {
+ @Nullable
+ public PackageInfo getPackageInfo(String packageName,
+ @PackageInfoFlags int flags) {
Preconditions.checkState(mAllPackagesCache != null,
"APEX packages have not been scanned");
boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0;
@@ -564,6 +578,36 @@ public abstract class ApexManager {
}
@Override
+ @Nullable
+ public String getActiveApexPackageNameContainingPackage(
+ @NonNull AndroidPackage containedPackage) {
+ Preconditions.checkState(mPackageNameToApexModuleName != null,
+ "APEX packages have not been scanned");
+
+ Objects.requireNonNull(containedPackage);
+
+ synchronized (mLock) {
+ int numApksInApex = mApksInApex.size();
+ for (int apkInApexNum = 0; apkInApexNum < numApksInApex; apkInApexNum++) {
+ if (mApksInApex.valueAt(apkInApexNum).contains(
+ containedPackage.getPackageName())) {
+ String apexModuleName = mApksInApex.keyAt(apkInApexNum);
+
+ int numApexPkgs = mPackageNameToApexModuleName.size();
+ for (int apexPkgNum = 0; apexPkgNum < numApexPkgs; apexPkgNum++) {
+ if (mPackageNameToApexModuleName.valueAt(apexPkgNum).equals(
+ apexModuleName)) {
+ return mPackageNameToApexModuleName.keyAt(apexPkgNum);
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+ @Override
@Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) {
try {
ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId);
@@ -893,7 +937,7 @@ public abstract class ApexManager {
}
@Override
- PackageInfo getPackageInfo(String packageName, int flags) {
+ public PackageInfo getPackageInfo(String packageName, int flags) {
return null;
}
@@ -918,6 +962,15 @@ public abstract class ApexManager {
}
@Override
+ @Nullable
+ public String getActiveApexPackageNameContainingPackage(
+ @NonNull AndroidPackage containedPackage) {
+ Objects.requireNonNull(containedPackage);
+
+ return null;
+ }
+
+ @Override
ApexSessionInfo getStagedSessionInfo(int sessionId) {
throw new UnsupportedOperationException();
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 79d0c2db4448..9522cc5d7d40 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -40,6 +40,7 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;
+import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS;
@@ -128,6 +129,7 @@ import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
import com.android.server.Watchdog;
+import com.android.server.pm.ApexManager;
import com.android.server.pm.PackageManagerServiceUtils;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.SharedUserSetting;
@@ -3321,8 +3323,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged()
&& !platformPackage && platformPermission) {
if (!hasPrivappWhitelistEntry(perm, pkg)) {
- // Only report violations for apps on system image
- if (!mSystemReady && !pkgSetting.getPkgState().isUpdatedSystemApp()) {
+ ApexManager apexMgr = ApexManager.getInstance();
+ String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(pkg);
+
+ // Only enforce whitelist this on boot
+ if (!mSystemReady
+ // Updated system apps do not need to be whitelisted
+ && !pkgSetting.getPkgState().isUpdatedSystemApp()
+ // Apps that are in updated apexs' do not need to be whitelisted
+ && (apexContainingPkg == null || apexMgr.isFactory(
+ apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE)))) {
// it's only a reportable violation if the permission isn't explicitly denied
ArraySet<String> deniedPermissions = null;
if (pkg.isVendor()) {