Include GIDs for unenforced permissions.
When READ_EXTERNAL_STORAGE isn't enforced, grant its GID to all
launched processes. When changing enforcement, kill all processes
below foreground adjustment, causing them to be relaunched with
update GIDs.
Bug: 6131916
Change-Id: I6d83efc937919f13a1a7d9caac902e572869406a
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index a3cc352..22793c0 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1055,6 +1055,15 @@
return true;
}
+ case KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ String reason = data.readString();
+ boolean res = killProcessesBelowForeground(reason);
+ reply.writeNoException();
+ reply.writeInt(res ? 1 : 0);
+ return true;
+ }
+
case START_RUNNING_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String pkg = data.readString();
@@ -2902,6 +2911,18 @@
reply.recycle();
return res;
}
+ @Override
+ public boolean killProcessesBelowForeground(String reason) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(reason);
+ mRemote.transact(KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION, data, reply, 0);
+ boolean res = reply.readInt() != 0;
+ data.recycle();
+ reply.recycle();
+ return res;
+ }
public void startRunning(String pkg, String cls, String action,
String indata) throws RemoteException {
Parcel data = Parcel.obtain();
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 31066b5..03f22f8 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -216,9 +216,10 @@
public void enterSafeMode() throws RemoteException;
public void noteWakeupAlarm(IIntentSender sender) throws RemoteException;
-
+
public boolean killPids(int[] pids, String reason, boolean secure) throws RemoteException;
-
+ public boolean killProcessesBelowForeground(String reason) throws RemoteException;
+
// Special low-level communication with activity manager.
public void startRunning(String pkg, String cls, String action,
String data) throws RemoteException;
@@ -573,4 +574,5 @@
int GET_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+140;
int REMOVE_CONTENT_PROVIDER_EXTERNAL_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+141;
int GET_MY_MEMORY_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+142;
+ int KILL_PROCESSES_BELOW_FOREGROUND_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+143;
}
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index d21212f..dd1dac2 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -6993,7 +6993,43 @@
}
return killed;
}
-
+
+ @Override
+ public boolean killProcessesBelowForeground(String reason) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("killProcessesBelowForeground() only available to system");
+ }
+
+ return killProcessesBelowAdj(ProcessList.FOREGROUND_APP_ADJ, reason);
+ }
+
+ private boolean killProcessesBelowAdj(int belowAdj, String reason) {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ throw new SecurityException("killProcessesBelowAdj() only available to system");
+ }
+
+ boolean killed = false;
+ synchronized (mPidsSelfLocked) {
+ final int size = mPidsSelfLocked.size();
+ for (int i = 0; i < size; i++) {
+ final int pid = mPidsSelfLocked.keyAt(i);
+ final ProcessRecord proc = mPidsSelfLocked.valueAt(i);
+ if (proc == null) continue;
+
+ final int adj = proc.setAdj;
+ if (adj > belowAdj && !proc.killedBackground) {
+ Slog.w(TAG, "Killing " + proc + " (adj " + adj + "): " + reason);
+ EventLog.writeEvent(
+ EventLogTags.AM_KILL, proc.pid, proc.processName, adj, reason);
+ killed = true;
+ proc.killedBackground = true;
+ Process.killProcessQuiet(pid);
+ }
+ }
+ }
+ return killed;
+ }
+
public final void startRunning(String pkg, String cls, String action,
String data) {
synchronized(this) {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index bc98f86..bb0f987 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -1577,7 +1577,16 @@
if (p != null) {
final PackageSetting ps = (PackageSetting)p.mExtras;
final SharedUserSetting suid = ps.sharedUser;
- return suid != null ? suid.gids : ps.gids;
+ int[] gids = suid != null ? suid.gids : ps.gids;
+
+ // include GIDs for any unenforced permissions
+ if (!isPermissionEnforcedLocked(READ_EXTERNAL_STORAGE)) {
+ final BasePermission basePerm = mSettings.mPermissions.get(
+ READ_EXTERNAL_STORAGE);
+ gids = appendInts(gids, basePerm.gids);
+ }
+
+ return gids;
}
}
// stupid thing to indicate an error.
@@ -8854,6 +8863,19 @@
if (mSettings.mReadExternalStorageEnforcement != enforcement) {
mSettings.mReadExternalStorageEnforcement = enforcement;
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);
+ }
+ }
}
}
} else {