Introduce security checks to startDreamActivity

This CL checks that the caller is the dream package and that the
device is dreaming when the activity is started.

isDream was instroduced in order to exempt the DreamActivity from
background start check. setAllowBackgroundActivityStart does that
more cleanly.

Bug: 152281628

Test: m && flashall && verify dream works

Change-Id: Id6161f923f3350d482b3452a78a792a541dcf1a1
This commit is contained in:
Galia Peycheva
2020-03-19 20:28:09 +01:00
parent 480275a197
commit ed401cc16d
4 changed files with 47 additions and 47 deletions

View File

@@ -1049,6 +1049,7 @@ public class DreamService extends Service implements Window.Callback {
// DreamServiceWrapper.onActivityCreated.
if (!mWindowless) {
Intent i = new Intent(this, DreamActivity.class);
i.setPackage(getApplicationContext().getPackageName());
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.putExtra(DreamActivity.EXTRA_CALLBACK, mDreamServiceWrapper);

View File

@@ -341,7 +341,6 @@ class ActivityStarter {
int filterCallingUid;
PendingIntentRecord originatingPendingIntent;
boolean allowBackgroundActivityStart;
boolean isDream;
/**
* If set to {@code true}, allows this activity start to look into
@@ -393,7 +392,6 @@ class ActivityStarter {
filterCallingUid = UserHandle.USER_NULL;
originatingPendingIntent = null;
allowBackgroundActivityStart = false;
isDream = false;
}
/**
@@ -434,7 +432,6 @@ class ActivityStarter {
filterCallingUid = request.filterCallingUid;
originatingPendingIntent = request.originatingPendingIntent;
allowBackgroundActivityStart = request.allowBackgroundActivityStart;
isDream = request.isDream;
}
/**
@@ -985,7 +982,7 @@ class ActivityStarter {
restrictedBgActivity = shouldAbortBackgroundActivityStart(callingUid,
callingPid, callingPackage, realCallingUid, realCallingPid, callerApp,
request.originatingPendingIntent, request.allowBackgroundActivityStart,
request.isDream, intent);
intent);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
@@ -1195,7 +1192,7 @@ class ActivityStarter {
boolean shouldAbortBackgroundActivityStart(int callingUid, int callingPid,
final String callingPackage, int realCallingUid, int realCallingPid,
WindowProcessController callerApp, PendingIntentRecord originatingPendingIntent,
boolean allowBackgroundActivityStart, boolean isDream, Intent intent) {
boolean allowBackgroundActivityStart, Intent intent) {
// don't abort for the most important UIDs
final int callingAppId = UserHandle.getAppId(callingUid);
if (callingUid == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID
@@ -1203,10 +1200,6 @@ class ActivityStarter {
return false;
}
// don't abort if this is the dream activity
if (isDream) {
return false;
}
// don't abort if the callingUid has a visible window or is a persistent system process
final int callingUidProcState = mService.getUidState(callingUid);
final boolean callingUidHasAnyVisibleWindow =
@@ -2717,11 +2710,6 @@ class ActivityStarter {
return this;
}
ActivityStarter setIsDream(boolean isDream) {
mRequest.isDream = isDream;
return this;
}
void dump(PrintWriter pw, String prefix) {
prefix = prefix + " ";
pw.print(prefix);

View File

@@ -212,7 +212,6 @@ import android.os.storage.IStorageManager;
import android.os.storage.StorageManager;
import android.provider.Settings;
import android.service.dreams.DreamActivity;
import android.service.dreams.DreamManagerInternal;
import android.service.voice.IVoiceInteractionSession;
import android.service.voice.VoiceInteractionManagerInternal;
import android.sysprop.DisplayProperties;
@@ -1245,36 +1244,29 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
}
@Override
public boolean startDreamActivity(Intent intent) {
final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
private void enforceCallerIsDream(String callerPackageName) {
final long origId = Binder.clearCallingIdentity();
// The dream activity is only called for non-doze dreams.
final ComponentName currentDream = LocalServices.getService(DreamManagerInternal.class)
.getActiveDreamComponent(/* doze= */ false);
if (currentDream == null || currentDream.getPackageName() == null
|| !currentDream.getPackageName().equals(process.mInfo.packageName)) {
Slog.e(TAG, "Calling package is not the current dream package. "
+ "Aborting startDreamActivity...");
return false;
try {
if (!ActivityRecord.canLaunchDreamActivity(callerPackageName)) {
throw new SecurityException("The dream activity can be started only when the device"
+ " is dreaming and only by the active dream package.");
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}
@Override
public boolean startDreamActivity(@NonNull Intent intent) {
assertPackageMatchesCallingUid(intent.getPackage());
enforceCallerIsDream(intent.getPackage());
final ActivityInfo a = new ActivityInfo();
a.theme = com.android.internal.R.style.Theme_Dream;
a.exported = true;
a.name = DreamActivity.class.getName();
a.packageName = process.mInfo.packageName;
a.applicationInfo = process.mInfo;
a.processName = process.mInfo.processName;
a.uiOptions = process.mInfo.uiOptions;
a.taskAffinity = "android:" + a.packageName + "/dream";
a.enabled = true;
a.launchMode = ActivityInfo.LAUNCH_SINGLE_INSTANCE;
a.persistableMode = ActivityInfo.PERSIST_NEVER;
a.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
a.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
@@ -1283,15 +1275,34 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchActivityType(ACTIVITY_TYPE_DREAM);
try {
getActivityStartController().obtainStarter(intent, "dream")
.setActivityInfo(a)
.setActivityOptions(options.toBundle())
.setIsDream(true)
.execute();
return true;
} finally {
Binder.restoreCallingIdentity(origId);
synchronized (mGlobalLock) {
final WindowProcessController process = mProcessMap.getProcess(Binder.getCallingPid());
a.packageName = process.mInfo.packageName;
a.applicationInfo = process.mInfo;
a.processName = process.mInfo.processName;
a.uiOptions = process.mInfo.uiOptions;
a.taskAffinity = "android:" + a.packageName + "/dream";
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
try {
getActivityStartController().obtainStarter(intent, "dream")
.setCallingUid(callingUid)
.setCallingPid(callingPid)
.setActivityInfo(a)
.setActivityOptions(options.toBundle())
// To start the dream from background, we need to start it from a persistent
// system process. Here we set the real calling uid to the system server uid
.setRealCallingUid(Binder.getCallingUid())
.setAllowBackgroundActivityStart(true)
.execute();
return true;
} finally {
Binder.restoreCallingIdentity(origId);
}
}
}
@@ -2478,7 +2489,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
final ActivityStarter starter = getActivityStartController().obtainStarter(
null /* intent */, "moveTaskToFront");
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid, callingPackage, -1,
-1, callerApp, null, false, false, null)) {
-1, callerApp, null, false, null)) {
if (!isBackgroundActivityStartsEnabled()) {
return;
}

View File

@@ -111,7 +111,7 @@ class AppTaskImpl extends IAppTask.Stub {
final ActivityStarter starter = mService.getActivityStartController().obtainStarter(
null /* intent */, "moveToFront");
if (starter.shouldAbortBackgroundActivityStart(callingUid, callingPid,
callingPackage, -1, -1, callerApp, null, false, false, null)) {
callingPackage, -1, -1, callerApp, null, false, null)) {
if (!mService.isBackgroundActivityStartsEnabled()) {
return;
}