diff options
3 files changed, 45 insertions, 21 deletions
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java index 87d14b9..0ca800f 100644 --- a/core/java/android/content/ContentResolver.java +++ b/core/java/android/content/ContentResolver.java @@ -329,7 +329,7 @@ public abstract class ContentResolver { try { String type = ActivityManagerNative.getDefault().getProviderMimeType( - url, UserHandle.myUserId()); + ContentProvider.getUriWithoutUserId(url), resolveUserId(url)); return type; } catch (RemoteException e) { // Arbitrary and not worth documenting, as Activity diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index c7c7a92..4455901 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -8971,8 +8971,10 @@ public final class ActivityManagerService extends ActivityManagerNative } /** - * Allows app to retrieve the MIME type of a URI without having permission - * to access its content provider. + * Allows apps to retrieve the MIME type of a URI. + * If an app is in the same user as the ContentProvider, or if it is allowed to interact across + * users, then it does not need permission to access the ContentProvider. + * Either, it needs cross-user uri grants. * * CTS tests for this functionality can be run with "runtest cts-appsecurity". * @@ -8981,12 +8983,22 @@ public final class ActivityManagerService extends ActivityManagerNative */ public String getProviderMimeType(Uri uri, int userId) { enforceNotIsolatedCaller("getProviderMimeType"); - userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), - userId, false, ALLOW_NON_FULL_IN_PROFILE, "getProviderMimeType", null); final String name = uri.getAuthority(); - final long ident = Binder.clearCallingIdentity(); + int callingUid = Binder.getCallingUid(); + int callingPid = Binder.getCallingPid(); + long ident = 0; + boolean clearedIdentity = false; + userId = unsafeConvertIncomingUser(userId); + if (UserHandle.getUserId(callingUid) != userId) { + if (checkComponentPermission(INTERACT_ACROSS_USERS, callingPid, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED + || checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) { + clearedIdentity = true; + ident = Binder.clearCallingIdentity(); + } + } ContentProviderHolder holder = null; - try { holder = getContentProviderExternalUnchecked(name, null, userId); if (holder != null) { @@ -8996,10 +9008,17 @@ public final class ActivityManagerService extends ActivityManagerNative Log.w(TAG, "Content provider dead retrieving " + uri, e); return null; } finally { - if (holder != null) { - removeContentProviderExternalUnchecked(name, null, userId); + // We need to clear the identity to call removeContentProviderExternalUnchecked + if (!clearedIdentity) { + ident = Binder.clearCallingIdentity(); + } + try { + if (holder != null) { + removeContentProviderExternalUnchecked(name, null, userId); + } + } finally { + Binder.restoreCallingIdentity(ident); } - Binder.restoreCallingIdentity(ident); } return null; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 44b7f01..36dec3e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -4635,12 +4635,12 @@ public class PackageManagerService extends IPackageManager.Stub { // 2.) we are defering a needed dexopt // 3.) we are skipping an unneeded dexopt final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); - for (String path : paths) { - for (String dexCodeInstructionSet : dexCodeInstructionSets) { - if (!forceDex && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) { - continue; - } + for (String dexCodeInstructionSet : dexCodeInstructionSets) { + if (!forceDex && pkg.mDexOptPerformed.contains(dexCodeInstructionSet)) { + continue; + } + for (String path : paths) { try { // This will return DEXOPT_NEEDED if we either cannot find any odex file for this // patckage or the one we find does not match the image checksum (i.e. it was @@ -4661,10 +4661,9 @@ public class PackageManagerService extends IPackageManager.Stub { // just result in an error again. Also, don't bother dexopting for other // paths & ISAs. return DEX_OPT_FAILED; - } else { - performedDexOpt = true; - pkg.mDexOptPerformed.add(dexCodeInstructionSet); } + + performedDexOpt = true; } else if (!defer && isDexOptNeeded == DexFile.PATCHOAT_NEEDED) { Log.i(TAG, "Running patchoat on: " + pkg.applicationInfo.packageName); final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); @@ -4676,10 +4675,9 @@ public class PackageManagerService extends IPackageManager.Stub { // just result in an error again. Also, don't bother dexopting for other // paths & ISAs. return DEX_OPT_FAILED; - } else { - performedDexOpt = true; - pkg.mDexOptPerformed.add(dexCodeInstructionSet); } + + performedDexOpt = true; } // We're deciding to defer a needed dexopt. Don't bother dexopting for other @@ -4706,6 +4704,13 @@ public class PackageManagerService extends IPackageManager.Stub { return DEX_OPT_FAILED; } } + + // At this point we haven't failed dexopt and we haven't deferred dexopt. We must + // either have either succeeded dexopt, or have had isDexOptNeededInternal tell us + // it isn't required. We therefore mark that this package doesn't need dexopt unless + // it's forced. performedDexOpt will tell us whether we performed dex-opt or skipped + // it. + pkg.mDexOptPerformed.add(dexCodeInstructionSet); } // If we've gotten here, we're sure that no error occurred and that we haven't |
