diff options
7 files changed, 103 insertions, 49 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 68d4cf108891..2fef250228b1 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1583,7 +1583,8 @@ final class ApplicationPackageManager extends PackageManager { public void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, int targetUserId, int flags) { try { - mPM.addCrossProfileIntentFilter(filter, sourceUserId, targetUserId, flags); + mPM.addCrossProfileIntentFilter(filter, mContext.getOpPackageName(), + mContext.getUserId(), sourceUserId, targetUserId, flags); } catch (RemoteException e) { // Should never happen! } @@ -1607,7 +1608,8 @@ final class ApplicationPackageManager extends PackageManager { @Override public void clearCrossProfileIntentFilters(int sourceUserId) { try { - mPM.clearCrossProfileIntentFilters(sourceUserId); + mPM.clearCrossProfileIntentFilters(sourceUserId, mContext.getOpPackageName(), + mContext.getUserId()); } catch (RemoteException e) { // Should never happen! } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 1f2f18a23f02..70cbd471b30f 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -2391,8 +2391,9 @@ public class DevicePolicyManager { } /** - * Called by a profile owner to remove the cross-profile intent filters from the managed profile - * and from the parent. + * Called by a profile owner to remove the cross-profile intent filters that go from the + * managed profile to the parent, or from the parent to the managed profile. + * Only removes those that have been set by the profile owner. * @param admin Which {@link DeviceAdminReceiver} this request is associated with. */ public void clearCrossProfileIntentFilters(ComponentName admin) { diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index 72c85ee62fbf..7196372edf4f 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -244,13 +244,13 @@ interface IPackageManager { void clearPackagePersistentPreferredActivities(String packageName, int userId); - void addCrossProfileIntentFilter(in IntentFilter intentFilter, int sourceUserId, int targetUserId, - int flags); + void addCrossProfileIntentFilter(in IntentFilter intentFilter, String ownerPackage, + int ownerUserId, int sourceUserId, int targetUserId, int flags); void addCrossProfileIntentsForPackage(in String packageName, int sourceUserId, int targetUserId); - void clearCrossProfileIntentFilters(int sourceUserId); + void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage, int ownerUserId); /** * Report the set of 'Home' activity candidates, plus (if any) which of them diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 62611efa5db0..c5dcd8ea5786 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -205,13 +205,6 @@ public abstract class PackageManager { public static final int NO_CROSS_PROFILE = 0x00020000; /** - * Flag for {@link addCrossProfileIntentFilter}: if the cross-profile intent has been set by the - * profile owner. - * @hide - */ - public static final int SET_BY_PROFILE_OWNER= 0x00000001; - - /** * Flag for {@link addCrossProfileIntentFilter}: if this flag is set: * when resolving an intent that matches the {@link CrossProfileIntentFilter}, the current * profile will be skipped. @@ -3744,9 +3737,10 @@ public abstract class PackageManager { * Adds a {@link CrossProfileIntentFilter}. After calling this method all intents sent from the * user with id sourceUserId can also be be resolved by activities in the user with id * targetUserId if they match the specified intent filter. - * @param filter the {@link IntentFilter} the intent has to match - * @param removable if set to false, {@link clearCrossProfileIntentFilters} will not remove this - * {@link CrossProfileIntentFilter} + * @param filter The {@link IntentFilter} the intent has to match + * @param sourceUserId The source user id. + * @param targetUserId The target user id. + * @param flags The only possible value is {@link SKIP_CURRENT_PROFILE} * @hide */ public abstract void addCrossProfileIntentFilter(IntentFilter filter, int sourceUserId, @@ -3754,8 +3748,8 @@ public abstract class PackageManager { /** * Clearing {@link CrossProfileIntentFilter}s which have the specified user as their - * source, and have been set by the profile owner - * @param sourceUserId + * source, and have been set by the app calling this method. + * @param sourceUserId The source user id. * @hide */ public abstract void clearCrossProfileIntentFilters(int sourceUserId); diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java index 3ce19c1fe43a..c61d344f48e6 100644 --- a/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java +++ b/services/core/java/com/android/server/pm/CrossProfileIntentFilter.java @@ -33,17 +33,24 @@ import android.os.UserHandle; class CrossProfileIntentFilter extends IntentFilter { private static final String ATTR_TARGET_USER_ID = "targetUserId"; private static final String ATTR_FLAGS = "flags"; + private static final String ATTR_OWNER_USER_ID = "ownerUserId"; + private static final String ATTR_OWNER_PACKAGE = "ownerPackage"; private static final String ATTR_FILTER = "filter"; private static final String TAG = "CrossProfileIntentFilter"; // If the intent matches the IntentFilter, then it can be forwarded to this userId. final int mTargetUserId; + final int mOwnerUserId; // userId of the app which has set this CrossProfileIntentFilter. + final String mOwnerPackage; // packageName of the app. final int mFlags; - CrossProfileIntentFilter(IntentFilter filter, int targetUserId, int flags) { + CrossProfileIntentFilter(IntentFilter filter, String ownerPackage, int ownerUserId, + int targetUserId, int flags) { super(filter); mTargetUserId = targetUserId; + mOwnerUserId = ownerUserId; + mOwnerPackage = ownerPackage; mFlags = flags; } @@ -55,25 +62,20 @@ class CrossProfileIntentFilter extends IntentFilter { return mFlags; } + public int getOwnerUserId() { + return mOwnerUserId; + } + + public String getOwnerPackage() { + return mOwnerPackage; + } + CrossProfileIntentFilter(XmlPullParser parser) throws XmlPullParserException, IOException { - String targetUserIdString = parser.getAttributeValue(null, ATTR_TARGET_USER_ID); - if (targetUserIdString == null) { - String msg = "Missing element under " + TAG +": " + ATTR_TARGET_USER_ID + " at " + - parser.getPositionDescription(); - PackageManagerService.reportSettingsProblem(Log.WARN, msg); - mTargetUserId = UserHandle.USER_NULL; - } else { - mTargetUserId = Integer.parseInt(targetUserIdString); - } - String flagsString = parser.getAttributeValue(null, ATTR_FLAGS); - if (flagsString == null) { - String msg = "Missing element under " + TAG +": " + ATTR_FLAGS + " at " + - parser.getPositionDescription(); - PackageManagerService.reportSettingsProblem(Log.WARN, msg); - mFlags = 0; - } else { - mFlags = Integer.parseInt(flagsString); - } + mTargetUserId = getIntFromXml(parser, ATTR_TARGET_USER_ID, UserHandle.USER_NULL); + mOwnerUserId = getIntFromXml(parser, ATTR_OWNER_USER_ID, UserHandle.USER_NULL); + mOwnerPackage = getStringFromXml(parser, ATTR_OWNER_PACKAGE, ""); + mFlags = getIntFromXml(parser, ATTR_FLAGS, 0); + int outerDepth = parser.getDepth(); String tagName = parser.getName(); int type; @@ -103,9 +105,31 @@ class CrossProfileIntentFilter extends IntentFilter { } } + String getStringFromXml(XmlPullParser parser, String attribute, String defaultValue) { + String value = parser.getAttributeValue(null, attribute); + if (value == null) { + String msg = "Missing element under " + TAG +": " + attribute + " at " + + parser.getPositionDescription(); + PackageManagerService.reportSettingsProblem(Log.WARN, msg); + return defaultValue; + } else { + return value; + } + } + + int getIntFromXml(XmlPullParser parser, String attribute, int defaultValue) { + String stringValue = getStringFromXml(parser, attribute, null); + if (stringValue != null) { + return Integer.parseInt(stringValue); + } + return defaultValue; + } + public void writeToXml(XmlSerializer serializer) throws IOException { serializer.attribute(null, ATTR_TARGET_USER_ID, Integer.toString(mTargetUserId)); serializer.attribute(null, ATTR_FLAGS, Integer.toString(mFlags)); + serializer.attribute(null, ATTR_OWNER_USER_ID, Integer.toString(mOwnerUserId)); + serializer.attribute(null, ATTR_OWNER_PACKAGE, mOwnerPackage); serializer.startTag(null, ATTR_FILTER); super.writeToXml(serializer); serializer.endTag(null, ATTR_FILTER); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index a07eb7e75d2c..68ae6ff65c91 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -11635,22 +11635,25 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - public void addCrossProfileIntentFilter(IntentFilter intentFilter, int sourceUserId, - int targetUserId, int flags) { + public void addCrossProfileIntentFilter(IntentFilter intentFilter, String ownerPackage, + int ownerUserId, int sourceUserId, int targetUserId, int flags) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); + int callingUid = Binder.getCallingUid(); + enforceOwnerRights(ownerPackage, ownerUserId, callingUid); if (intentFilter.countActions() == 0) { Slog.w(TAG, "Cannot set a crossProfile intent filter with no filter actions"); return; } synchronized (mPackages) { CrossProfileIntentFilter filter = new CrossProfileIntentFilter(intentFilter, - targetUserId, flags); + ownerPackage, UserHandle.getUserId(callingUid), targetUserId, flags); mSettings.editCrossProfileIntentResolverLPw(sourceUserId).addFilter(filter); mSettings.writePackageRestrictionsLPr(sourceUserId); } } + @Override public void addCrossProfileIntentsForPackage(String packageName, int sourceUserId, int targetUserId) { mContext.enforceCallingOrSelfPermission( @@ -11668,16 +11671,21 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - public void clearCrossProfileIntentFilters(int sourceUserId) { + public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage, + int ownerUserId) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); + int callingUid = Binder.getCallingUid(); + enforceOwnerRights(ownerPackage, ownerUserId, callingUid); + int callingUserId = UserHandle.getUserId(callingUid); synchronized (mPackages) { CrossProfileIntentResolver resolver = mSettings.editCrossProfileIntentResolverLPw(sourceUserId); HashSet<CrossProfileIntentFilter> set = new HashSet<CrossProfileIntentFilter>(resolver.filterSet()); for (CrossProfileIntentFilter filter : set) { - if ((filter.getFlags() & PackageManager.SET_BY_PROFILE_OWNER) != 0) { + if (filter.getOwnerPackage().equals(ownerPackage) + && filter.getOwnerUserId() == callingUserId) { resolver.removeFilter(filter); } } @@ -11685,6 +11693,29 @@ public class PackageManagerService extends IPackageManager.Stub { } } + // Enforcing that callingUid is owning pkg on userId + private void enforceOwnerRights(String pkg, int userId, int callingUid) { + // The system owns everything. + if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { + return; + } + int callingUserId = UserHandle.getUserId(callingUid); + if (callingUserId != userId) { + throw new SecurityException("calling uid " + callingUid + + " pretends to own " + pkg + " on user " + userId + " but belongs to user " + + callingUserId); + } + PackageInfo pi = getPackageInfo(pkg, 0, callingUserId); + if (pi == null) { + throw new IllegalArgumentException("Unknown package " + pkg + " on user " + + callingUserId); + } + if (!UserHandle.isSameApp(pi.applicationInfo.uid, callingUid)) { + throw new SecurityException("Calling uid " + callingUid + + " does not own package " + pkg); + } + } + @Override public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) { Intent intent = new Intent(Intent.ACTION_MAIN); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index dc55e6d5bbba..c54c4fb65ccb 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3606,12 +3606,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { long id = Binder.clearCallingIdentity(); try { if ((flags & DevicePolicyManager.FLAG_PARENT_CAN_ACCESS_MANAGED) != 0) { - pm.addCrossProfileIntentFilter(filter, callingUserId, UserHandle.USER_OWNER, - PackageManager.SET_BY_PROFILE_OWNER); + pm.addCrossProfileIntentFilter(filter, who.getPackageName(), + mContext.getUserId(), callingUserId, UserHandle.USER_OWNER, 0); } if ((flags & DevicePolicyManager.FLAG_MANAGED_CAN_ACCESS_PARENT) != 0) { - pm.addCrossProfileIntentFilter(filter, UserHandle.USER_OWNER, callingUserId, - PackageManager.SET_BY_PROFILE_OWNER); + pm.addCrossProfileIntentFilter(filter, who.getPackageName(), + mContext.getUserId(), UserHandle.USER_OWNER, callingUserId, 0); } } catch (RemoteException re) { // Shouldn't happen @@ -3631,10 +3631,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { IPackageManager pm = AppGlobals.getPackageManager(); long id = Binder.clearCallingIdentity(); try { - pm.clearCrossProfileIntentFilters(callingUserId); + pm.clearCrossProfileIntentFilters(callingUserId, who.getPackageName(), + callingUserId); // If we want to support multiple managed profiles, we will have to only remove // those that have callingUserId as their target. - pm.clearCrossProfileIntentFilters(UserHandle.USER_OWNER); + pm.clearCrossProfileIntentFilters(UserHandle.USER_OWNER, who.getPackageName(), + callingUserId); } catch (RemoteException re) { // Shouldn't happen } finally { |