diff options
| author | 2022-09-20 05:29:05 +0000 | |
|---|---|---|
| committer | 2022-09-20 05:29:05 +0000 | |
| commit | 169e872ca494a514302822ad6cf66de6f522affd (patch) | |
| tree | aac7390f57b1e4194b6eedf3696a57c8e018520d | |
| parent | 02493c976f22a9785c9fd620c53f0854571d9027 (diff) | |
| parent | 3a8bfc972e6327045b255845800db9947037a963 (diff) | |
Merge "Honor app visibility when get MIME type from ContentProvider"
| -rw-r--r-- | services/core/java/com/android/server/am/ContentProviderHelper.java | 98 |
1 files changed, 64 insertions, 34 deletions
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java index 86c97707362a..a97173d2695f 100644 --- a/services/core/java/com/android/server/am/ContentProviderHelper.java +++ b/services/core/java/com/android/server/am/ContentProviderHelper.java @@ -29,6 +29,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU; import static com.android.server.am.ActivityManagerService.TAG_MU; import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_PROVIDER; +import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -48,7 +49,6 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManagerInternal; import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.content.pm.UserInfo; @@ -960,20 +960,22 @@ public class ContentProviderHelper { String getProviderMimeType(Uri uri, int userId) { mService.enforceNotIsolatedCaller("getProviderMimeType"); final String name = uri.getAuthority(); - int callingUid = Binder.getCallingUid(); - int callingPid = Binder.getCallingPid(); - long ident = 0; - boolean clearedIdentity = false; - userId = mService.mUserController.unsafeConvertIncomingUser(userId); - if (canClearIdentity(callingPid, callingUid, userId)) { - clearedIdentity = true; - ident = Binder.clearCallingIdentity(); + final int callingUid = Binder.getCallingUid(); + final int callingPid = Binder.getCallingPid(); + final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId); + final long ident = canClearIdentity(callingPid, callingUid, safeUserId) + ? Binder.clearCallingIdentity() : 0; + final ContentProviderHolder holder; + try { + holder = getContentProviderExternalUnchecked(name, null /* token */, callingUid, + "*getmimetype*", safeUserId); + } finally { + if (ident != 0) { + Binder.restoreCallingIdentity(ident); + } } - ContentProviderHolder holder = null; try { - holder = getContentProviderExternalUnchecked(name, null, callingUid, - "*getmimetype*", userId); - if (holder != null) { + if (isHolderVisibleToCaller(holder, callingUid, safeUserId)) { final IBinder providerConnection = holder.connection; final ComponentName providerName = holder.info.getComponentName(); // Note: creating a new Runnable instead of using a lambda here since lambdas in @@ -992,6 +994,13 @@ public class ContentProviderHelper { return holder.provider.getType(uri); } finally { mService.mHandler.removeCallbacks(providerNotResponding); + // We need to clear the identity to call removeContentProviderExternalUnchecked + final long token = Binder.clearCallingIdentity(); + try { + removeContentProviderExternalUnchecked(name, null /* token */, safeUserId); + } finally { + Binder.restoreCallingIdentity(token); + } } } } catch (RemoteException e) { @@ -1000,18 +1009,6 @@ public class ContentProviderHelper { } catch (Exception e) { Log.w(TAG, "Exception while determining type of " + uri, e); return null; - } finally { - // 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); - } } return null; @@ -1029,12 +1026,20 @@ public class ContentProviderHelper { final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId); - final long ident = canClearIdentity(callingPid, callingUid, userId) + final long ident = canClearIdentity(callingPid, callingUid, safeUserId) ? Binder.clearCallingIdentity() : 0; + final ContentProviderHolder holder; try { - final ContentProviderHolder holder = getContentProviderExternalUnchecked(name, null, - callingUid, "*getmimetype*", safeUserId); - if (holder != null) { + holder = getContentProviderExternalUnchecked(name, null /* token */, callingUid, + "*getmimetype*", safeUserId); + } finally { + if (ident != 0) { + Binder.restoreCallingIdentity(ident); + } + } + + try { + if (isHolderVisibleToCaller(holder, callingUid, safeUserId)) { holder.provider.getTypeAsync(uri, new RemoteCallback(result -> { final long identity = Binder.clearCallingIdentity(); try { @@ -1050,8 +1055,6 @@ public class ContentProviderHelper { } catch (RemoteException e) { Log.w(TAG, "Content provider dead retrieving " + uri, e); resultCallback.sendResult(Bundle.EMPTY); - } finally { - Binder.restoreCallingIdentity(ident); } } @@ -1067,6 +1070,35 @@ public class ContentProviderHelper { callingUid, -1, true) == PackageManager.PERMISSION_GRANTED; } + private boolean isHolderVisibleToCaller(@Nullable ContentProviderHolder holder, int callingUid, + @UserIdInt int userId) { + if (holder == null || holder.info == null) { + return false; + } + + if (isAuthorityRedirectedForCloneProfile(holder.info.authority) + && resolveParentUserIdForCloneProfile(userId) != userId) { + // Since clone profile shares certain providers with its parent and the access is + // re-directed as well, the holder may not actually be installed on the clone profile. + return !mService.getPackageManagerInternal().filterAppAccess(holder.info.packageName, + callingUid, userId, false /* filterUninstalled */); + } + + return !mService.getPackageManagerInternal().filterAppAccess(holder.info.packageName, + callingUid, userId); + } + + private static @UserIdInt int resolveParentUserIdForCloneProfile(@UserIdInt int userId) { + final UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); + final UserInfo userInfo = umInternal.getUserInfo(userId); + + if (userInfo == null || !userInfo.isCloneProfile()) { + return userId; + } + + return umInternal.getProfileParentId(userId); + } + /** * Check if the calling UID has a possible chance at accessing the provider * at the given authority and user. @@ -1135,9 +1167,7 @@ public class ContentProviderHelper { "*checkContentProviderUriPermission*", userId); if (holder != null) { - final PackageManagerInternal packageManagerInt = LocalServices.getService( - PackageManagerInternal.class); - final AndroidPackage androidPackage = packageManagerInt + final AndroidPackage androidPackage = mService.getPackageManagerInternal() .getPackage(Binder.getCallingUid()); if (androidPackage == null) { return PackageManager.PERMISSION_DENIED; |