Loading core/java/android/content/ContentProvider.java +50 −4 Original line number Diff line number Diff line Loading @@ -48,10 +48,13 @@ import android.os.RemoteCallback; import android.os.RemoteException; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.permission.PermissionCheckerManager; import android.provider.MediaStore; import android.text.TextUtils; import android.util.Log; import android.util.SparseBooleanArray; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -134,9 +137,18 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall private boolean mExported; private boolean mNoPerms; private boolean mSingleUser; private SparseBooleanArray mUsersRedirectedToOwner = new SparseBooleanArray(); private ThreadLocal<AttributionSource> mCallingAttributionSource; /** * @hide */ public static boolean isAuthorityRedirectedForCloneProfile(String authority) { // For now, only MediaProvider gets redirected. return MediaStore.AUTHORITY.equals(authority); } private Transport mTransport = new Transport(); /** Loading Loading @@ -726,13 +738,47 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } boolean checkUser(int pid, int uid, Context context) { if (UserHandle.getUserId(uid) == context.getUserId() || mSingleUser) { int callingUserId = UserHandle.getUserId(uid); if (callingUserId == context.getUserId() || mSingleUser) { return true; } return context.checkPermission(INTERACT_ACROSS_USERS, pid, uid) if (context.checkPermission(INTERACT_ACROSS_USERS, pid, uid) == PackageManager.PERMISSION_GRANTED || context.checkPermission(INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED; == PackageManager.PERMISSION_GRANTED) { return true; } if (isAuthorityRedirectedForCloneProfile(mAuthority)) { if (mUsersRedirectedToOwner.indexOfKey(callingUserId) >= 0) { return mUsersRedirectedToOwner.get(callingUserId); } // Haven't seen this user yet, look it up try { UserHandle callingUser = UserHandle.getUserHandleForUid(uid); Context callingUserContext = mContext.createPackageContextAsUser("system", 0, callingUser); UserManager um = callingUserContext.getSystemService(UserManager.class); if (um != null && um.isCloneProfile()) { UserHandle parent = um.getProfileParent(callingUser); if (parent != null && parent.equals(context.getUser())) { mUsersRedirectedToOwner.put(callingUser.getIdentifier(), true); return true; } } } catch (PackageManager.NameNotFoundException e) { // ignore } mUsersRedirectedToOwner.put(UserHandle.getUserId(uid), false); return false; } return false; } /** Loading services/core/java/com/android/server/am/ContentProviderHelper.java +36 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.server.am; import static android.content.ContentProvider.isAuthorityRedirectedForCloneProfile; import static android.os.Process.PROC_CHAR; import static android.os.Process.PROC_OUT_LONG; import static android.os.Process.PROC_PARENS; Loading Loading @@ -46,6 +47,7 @@ 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; import android.database.ContentObserver; import android.net.Uri; import android.os.Binder; Loading @@ -72,6 +74,7 @@ import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.server.LocalServices; import com.android.server.RescueParty; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.parsing.pkg.AndroidPackage; import java.io.FileDescriptor; Loading Loading @@ -177,12 +180,22 @@ public class ContentProviderHelper { cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM); if (cpr != null) { cpi = cpr.info; if (mService.isSingleton( cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags) && mService.isValidSingletonCall( r == null ? callingUid : r.uid, cpi.applicationInfo.uid)) { userId = UserHandle.USER_SYSTEM; checkCrossUser = false; } else if (isAuthorityRedirectedForCloneProfile(name)) { UserManagerInternal umInternal = LocalServices.getService( UserManagerInternal.class); UserInfo userInfo = umInternal.getUserInfo(userId); if (userInfo != null && userInfo.isCloneProfile()) { userId = umInternal.getProfileParentId(userId); checkCrossUser = false; } } else { cpr = null; cpi = null; Loading Loading @@ -1026,6 +1039,7 @@ public class ContentProviderHelper { * at the given authority and user. */ String checkContentProviderAccess(String authority, int userId) { boolean checkUser = true; if (userId == UserHandle.USER_ALL) { mService.mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); Loading @@ -1041,6 +1055,17 @@ public class ContentProviderHelper { | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); if (cpi == null && isAuthorityRedirectedForCloneProfile(authority)) { // This might be a provider that's running only in the system user that's // also serving clone profiles cpi = AppGlobals.getPackageManager().resolveContentProvider(authority, ActivityManagerService.STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS | PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, UserHandle.USER_SYSTEM); } } catch (RemoteException ignored) { } if (cpi == null) { Loading @@ -1048,6 +1073,16 @@ public class ContentProviderHelper { + "; expected to find a valid ContentProvider for this authority"; } if (isAuthorityRedirectedForCloneProfile(authority)) { UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); UserInfo userInfo = umInternal.getUserInfo(userId); if (userInfo != null && userInfo.isCloneProfile()) { userId = umInternal.getProfileParentId(userId); checkUser = false; } } final int callingPid = Binder.getCallingPid(); ProcessRecord r; final String appName; Loading @@ -1060,7 +1095,7 @@ public class ContentProviderHelper { } return checkContentProviderPermission(cpi, callingPid, Binder.getCallingUid(), userId, true, appName); userId, checkUser, appName); } int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) { Loading services/core/java/com/android/server/pm/ComputerEngine.java +26 −9 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.Manifest.permission.DELETE_PACKAGES; import static android.Manifest.permission.INSTALL_PACKAGES; import static android.Manifest.permission.REQUEST_DELETE_PACKAGES; import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS; import static android.content.ContentProvider.isAuthorityRedirectedForCloneProfile; import static android.content.Intent.ACTION_MAIN; import static android.content.Intent.CATEGORY_DEFAULT; import static android.content.Intent.CATEGORY_HOME; Loading Loading @@ -92,14 +93,6 @@ import android.content.pm.SigningDetails; import android.content.pm.SigningInfo; import android.content.pm.UserInfo; import android.content.pm.VersionedPackage; import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; import com.android.server.pm.pkg.component.ParsedActivity; import com.android.server.pm.pkg.component.ParsedInstrumentation; import com.android.server.pm.pkg.component.ParsedIntentInfo; import com.android.server.pm.pkg.component.ParsedMainComponent; import com.android.server.pm.pkg.component.ParsedProvider; import com.android.server.pm.pkg.component.ParsedService; import com.android.server.pm.pkg.PackageUserStateUtils; import android.os.Binder; import android.os.Build; import android.os.IBinder; Loading Loading @@ -142,6 +135,14 @@ import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageStateUtils; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; import com.android.server.pm.pkg.PackageUserStateUtils; import com.android.server.pm.pkg.component.ParsedActivity; import com.android.server.pm.pkg.component.ParsedInstrumentation; import com.android.server.pm.pkg.component.ParsedIntentInfo; import com.android.server.pm.pkg.component.ParsedMainComponent; import com.android.server.pm.pkg.component.ParsedProvider; import com.android.server.pm.pkg.component.ParsedService; import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import com.android.server.pm.verify.domain.DomainVerificationUtils; import com.android.server.uri.UriGrantsManagerInternal; Loading Loading @@ -4617,8 +4618,24 @@ public class ComputerEngine implements Computer { } } if (!checkedGrants) { enforceCrossUserPermission(callingUid, userId, false, false, "resolveContentProvider"); boolean enforceCrossUser = true; if (isAuthorityRedirectedForCloneProfile(name)) { final UserManagerInternal umInternal = mInjector.getUserManagerInternal(); UserInfo userInfo = umInternal.getUserInfo(UserHandle.getUserId(callingUid)); if (userInfo != null && userInfo.isCloneProfile() && userInfo.profileGroupId == userId) { enforceCrossUser = false; } } if (enforceCrossUser) { enforceCrossUserPermission(callingUid, userId, false, false, "resolveContentProvider"); } } if (providerInfo == null) { return null; } Loading Loading
core/java/android/content/ContentProvider.java +50 −4 Original line number Diff line number Diff line Loading @@ -48,10 +48,13 @@ import android.os.RemoteCallback; import android.os.RemoteException; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.os.storage.StorageManager; import android.permission.PermissionCheckerManager; import android.provider.MediaStore; import android.text.TextUtils; import android.util.Log; import android.util.SparseBooleanArray; import com.android.internal.annotations.VisibleForTesting; Loading Loading @@ -134,9 +137,18 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall private boolean mExported; private boolean mNoPerms; private boolean mSingleUser; private SparseBooleanArray mUsersRedirectedToOwner = new SparseBooleanArray(); private ThreadLocal<AttributionSource> mCallingAttributionSource; /** * @hide */ public static boolean isAuthorityRedirectedForCloneProfile(String authority) { // For now, only MediaProvider gets redirected. return MediaStore.AUTHORITY.equals(authority); } private Transport mTransport = new Transport(); /** Loading Loading @@ -726,13 +738,47 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall } boolean checkUser(int pid, int uid, Context context) { if (UserHandle.getUserId(uid) == context.getUserId() || mSingleUser) { int callingUserId = UserHandle.getUserId(uid); if (callingUserId == context.getUserId() || mSingleUser) { return true; } return context.checkPermission(INTERACT_ACROSS_USERS, pid, uid) if (context.checkPermission(INTERACT_ACROSS_USERS, pid, uid) == PackageManager.PERMISSION_GRANTED || context.checkPermission(INTERACT_ACROSS_USERS_FULL, pid, uid) == PackageManager.PERMISSION_GRANTED; == PackageManager.PERMISSION_GRANTED) { return true; } if (isAuthorityRedirectedForCloneProfile(mAuthority)) { if (mUsersRedirectedToOwner.indexOfKey(callingUserId) >= 0) { return mUsersRedirectedToOwner.get(callingUserId); } // Haven't seen this user yet, look it up try { UserHandle callingUser = UserHandle.getUserHandleForUid(uid); Context callingUserContext = mContext.createPackageContextAsUser("system", 0, callingUser); UserManager um = callingUserContext.getSystemService(UserManager.class); if (um != null && um.isCloneProfile()) { UserHandle parent = um.getProfileParent(callingUser); if (parent != null && parent.equals(context.getUser())) { mUsersRedirectedToOwner.put(callingUser.getIdentifier(), true); return true; } } } catch (PackageManager.NameNotFoundException e) { // ignore } mUsersRedirectedToOwner.put(UserHandle.getUserId(uid), false); return false; } return false; } /** Loading
services/core/java/com/android/server/am/ContentProviderHelper.java +36 −1 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ */ package com.android.server.am; import static android.content.ContentProvider.isAuthorityRedirectedForCloneProfile; import static android.os.Process.PROC_CHAR; import static android.os.Process.PROC_OUT_LONG; import static android.os.Process.PROC_PARENS; Loading Loading @@ -46,6 +47,7 @@ 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; import android.database.ContentObserver; import android.net.Uri; import android.os.Binder; Loading @@ -72,6 +74,7 @@ import com.android.internal.os.BackgroundThread; import com.android.internal.util.ArrayUtils; import com.android.server.LocalServices; import com.android.server.RescueParty; import com.android.server.pm.UserManagerInternal; import com.android.server.pm.parsing.pkg.AndroidPackage; import java.io.FileDescriptor; Loading Loading @@ -177,12 +180,22 @@ public class ContentProviderHelper { cpr = mProviderMap.getProviderByName(name, UserHandle.USER_SYSTEM); if (cpr != null) { cpi = cpr.info; if (mService.isSingleton( cpi.processName, cpi.applicationInfo, cpi.name, cpi.flags) && mService.isValidSingletonCall( r == null ? callingUid : r.uid, cpi.applicationInfo.uid)) { userId = UserHandle.USER_SYSTEM; checkCrossUser = false; } else if (isAuthorityRedirectedForCloneProfile(name)) { UserManagerInternal umInternal = LocalServices.getService( UserManagerInternal.class); UserInfo userInfo = umInternal.getUserInfo(userId); if (userInfo != null && userInfo.isCloneProfile()) { userId = umInternal.getProfileParentId(userId); checkCrossUser = false; } } else { cpr = null; cpi = null; Loading Loading @@ -1026,6 +1039,7 @@ public class ContentProviderHelper { * at the given authority and user. */ String checkContentProviderAccess(String authority, int userId) { boolean checkUser = true; if (userId == UserHandle.USER_ALL) { mService.mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); Loading @@ -1041,6 +1055,17 @@ public class ContentProviderHelper { | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, userId); if (cpi == null && isAuthorityRedirectedForCloneProfile(authority)) { // This might be a provider that's running only in the system user that's // also serving clone profiles cpi = AppGlobals.getPackageManager().resolveContentProvider(authority, ActivityManagerService.STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS | PackageManager.MATCH_DISABLED_COMPONENTS | PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, UserHandle.USER_SYSTEM); } } catch (RemoteException ignored) { } if (cpi == null) { Loading @@ -1048,6 +1073,16 @@ public class ContentProviderHelper { + "; expected to find a valid ContentProvider for this authority"; } if (isAuthorityRedirectedForCloneProfile(authority)) { UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class); UserInfo userInfo = umInternal.getUserInfo(userId); if (userInfo != null && userInfo.isCloneProfile()) { userId = umInternal.getProfileParentId(userId); checkUser = false; } } final int callingPid = Binder.getCallingPid(); ProcessRecord r; final String appName; Loading @@ -1060,7 +1095,7 @@ public class ContentProviderHelper { } return checkContentProviderPermission(cpi, callingPid, Binder.getCallingUid(), userId, true, appName); userId, checkUser, appName); } int checkContentProviderUriPermission(Uri uri, int userId, int callingUid, int modeFlags) { Loading
services/core/java/com/android/server/pm/ComputerEngine.java +26 −9 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import static android.Manifest.permission.DELETE_PACKAGES; import static android.Manifest.permission.INSTALL_PACKAGES; import static android.Manifest.permission.REQUEST_DELETE_PACKAGES; import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS; import static android.content.ContentProvider.isAuthorityRedirectedForCloneProfile; import static android.content.Intent.ACTION_MAIN; import static android.content.Intent.CATEGORY_DEFAULT; import static android.content.Intent.CATEGORY_HOME; Loading Loading @@ -92,14 +93,6 @@ import android.content.pm.SigningDetails; import android.content.pm.SigningInfo; import android.content.pm.UserInfo; import android.content.pm.VersionedPackage; import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; import com.android.server.pm.pkg.component.ParsedActivity; import com.android.server.pm.pkg.component.ParsedInstrumentation; import com.android.server.pm.pkg.component.ParsedIntentInfo; import com.android.server.pm.pkg.component.ParsedMainComponent; import com.android.server.pm.pkg.component.ParsedProvider; import com.android.server.pm.pkg.component.ParsedService; import com.android.server.pm.pkg.PackageUserStateUtils; import android.os.Binder; import android.os.Build; import android.os.IBinder; Loading Loading @@ -142,6 +135,14 @@ import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageStateUtils; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; import com.android.server.pm.pkg.PackageUserStateUtils; import com.android.server.pm.pkg.component.ParsedActivity; import com.android.server.pm.pkg.component.ParsedInstrumentation; import com.android.server.pm.pkg.component.ParsedIntentInfo; import com.android.server.pm.pkg.component.ParsedMainComponent; import com.android.server.pm.pkg.component.ParsedProvider; import com.android.server.pm.pkg.component.ParsedService; import com.android.server.pm.pkg.parsing.PackageInfoWithoutStateUtils; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import com.android.server.pm.verify.domain.DomainVerificationUtils; import com.android.server.uri.UriGrantsManagerInternal; Loading Loading @@ -4617,8 +4618,24 @@ public class ComputerEngine implements Computer { } } if (!checkedGrants) { enforceCrossUserPermission(callingUid, userId, false, false, "resolveContentProvider"); boolean enforceCrossUser = true; if (isAuthorityRedirectedForCloneProfile(name)) { final UserManagerInternal umInternal = mInjector.getUserManagerInternal(); UserInfo userInfo = umInternal.getUserInfo(UserHandle.getUserId(callingUid)); if (userInfo != null && userInfo.isCloneProfile() && userInfo.profileGroupId == userId) { enforceCrossUser = false; } } if (enforceCrossUser) { enforceCrossUserPermission(callingUid, userId, false, false, "resolveContentProvider"); } } if (providerInfo == null) { return null; } Loading