From f1b782427fa5bc878ac0d5356ff8332143d3798b Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Mon, 8 Apr 2013 22:28:59 -0700 Subject: Kill processes when permissions are revoked. Some permissions are associated with gids, so we need to kill any running processes if their permission is revoked. We will do this for any permission being revoked, since the association between gids and permissions can change over time. Change-Id: Ieb7408e032539c4f21eb089d65a7a7e6c289f010 --- core/java/android/app/ActivityManagerNative.java | 22 ++++++++++ core/java/android/app/IActivityManager.java | 3 ++ .../android/server/am/ActivityManagerService.java | 15 +++++++ .../android/server/pm/PackageManagerService.java | 51 ++++++++++++++++------ 4 files changed, 78 insertions(+), 13 deletions(-) diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index aca4f9cdd311..c99051ba4dd6 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -1853,6 +1853,15 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM return true; } + case KILL_UID_TRANSACTION: { + data.enforceInterface(IActivityManager.descriptor); + int uid = data.readInt(); + String reason = data.readString(); + killUid(uid, reason); + reply.writeNoException(); + return true; + } + } return super.onTransact(code, data, reply, flags); @@ -3335,6 +3344,7 @@ class ActivityManagerProxy implements IActivityManager data.writeString(reason); data.writeInt(secure ? 1 : 0); mRemote.transact(KILL_PIDS_TRANSACTION, data, reply, 0); + reply.readException(); boolean res = reply.readInt() != 0; data.recycle(); reply.recycle(); @@ -4229,5 +4239,17 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } + public void killUid(int uid, String reason) throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + data.writeInt(uid); + data.writeString(reason); + mRemote.transact(KILL_UID_TRANSACTION, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + private IBinder mRemote; } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index cf4c72939a61..fa8839a66b3d 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -373,6 +373,8 @@ public interface IActivityManager extends IInterface { public void reportTopActivityExtras(IBinder token, Bundle extras) throws RemoteException; + public void killUid(int uid, String reason) throws RemoteException; + /* * Private non-Binder interfaces */ @@ -632,4 +634,5 @@ public interface IActivityManager extends IInterface { int GET_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+161; int REPORT_TOP_ACTIVITY_EXTRAS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+162; int GET_LAUNCHED_FROM_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+163; + int KILL_UID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+164; } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 7710f136702d..0eac52329b2b 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -3858,6 +3858,9 @@ public final class ActivityManagerService extends ActivityManagerNative if (app.userId != userId) { continue; } + if (appId >= 0 && UserHandle.getAppId(app.uid) != appId) { + continue; + } // Package has been specified, we want to hit all processes // that match it. We need to qualify this by the processes // that are running under the specified app and user ID. @@ -7732,6 +7735,18 @@ public final class ActivityManagerService extends ActivityManagerNative return killed; } + @Override + public void killUid(int uid, String reason) { + if (Binder.getCallingUid() != Process.SYSTEM_UID) { + throw new SecurityException("killUid only available to the system"); + } + synchronized (this) { + killPackageProcessesLocked(null, UserHandle.getAppId(uid), UserHandle.getUserId(uid), + ProcessList.FOREGROUND_APP_ADJ-1, false, true, true, false, + reason != null ? reason : "kill uid"); + } + } + @Override public boolean killProcessesBelowForeground(String reason) { if (Binder.getCallingUid() != Process.SYSTEM_UID) { diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index ca7bba21e9b2..12e6a0447aab 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -2308,6 +2308,8 @@ public class PackageManagerService extends IPackageManager.Stub { } public void revokePermission(String packageName, String permissionName) { + int changedAppId = -1; + synchronized (mPackages) { final PackageParser.Package pkg = mPackages.get(packageName); if (pkg == null) { @@ -2335,6 +2337,30 @@ public class PackageManagerService extends IPackageManager.Stub { gp.gids = removeInts(gp.gids, bp.gids); } mSettings.writeLPr(); + changedAppId = ps.appId; + } + } + + if (changedAppId >= 0) { + // We changed the perm on someone, kill its processes. + IActivityManager am = ActivityManagerNative.getDefault(); + if (am != null) { + final int callingUserId = UserHandle.getCallingUserId(); + final long ident = Binder.clearCallingIdentity(); + try { + //XXX we should only revoke for the calling user's app permissions, + // but for now we impact all users. + //am.killUid(UserHandle.getUid(callingUserId, changedAppId), + // "revoke " + permissionName); + int[] users = sUserManager.getUserIds(); + for (int user : users) { + am.killUid(UserHandle.getUid(user, changedAppId), + "revoke " + permissionName); + } + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } } } } @@ -10655,19 +10681,18 @@ public class PackageManagerService extends IPackageManager.Stub { || mSettings.mReadExternalStorageEnforced != enforced) { mSettings.mReadExternalStorageEnforced = enforced; mSettings.writeLPr(); - - // kill any non-foreground processes so we restart them and - // grant/revoke the GID. - final IActivityManager am = ActivityManagerNative.getDefault(); - if (am != null) { - final long token = Binder.clearCallingIdentity(); - try { - am.killProcessesBelowForeground("setPermissionEnforcement"); - } catch (RemoteException e) { - } finally { - Binder.restoreCallingIdentity(token); - } - } + } + } + // kill any non-foreground processes so we restart them and + // grant/revoke the GID. + final IActivityManager am = ActivityManagerNative.getDefault(); + if (am != null) { + final long token = Binder.clearCallingIdentity(); + try { + am.killProcessesBelowForeground("setPermissionEnforcement"); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(token); } } } else { -- cgit v1.2.3-59-g8ed1b