diff options
| -rw-r--r-- | services/core/java/com/android/server/pm/ApexManager.java | 85 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/permission/PermissionManagerService.java | 14 |
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()) { |