Do not resolve ActivityInfo in navigateUpTo
During navigateUpTo, it will first resolve the activity before creating the ActivityStarter. This bypasses the explicit intent filter enforcement introduced in T, exposing a security flaw that allows non-matching intents to be delivered to components. Bug: 238602879 Test: atest CtsWindowManagerDeviceTestCases Change-Id: I9aa3e27f753f2f809e74a8f421f8b68e4d610702 Merged-In: I9aa3e27f753f2f809e74a8f421f8b68e4d610702
This commit is contained in:
@@ -8045,8 +8045,9 @@ public class Activity extends ContextThemeWrapper
|
||||
resultData.prepareToLeaveProcess(this);
|
||||
}
|
||||
upIntent.prepareToLeaveProcess(this);
|
||||
return ActivityClient.getInstance().navigateUpTo(mToken, upIntent, resultCode,
|
||||
resultData);
|
||||
String resolvedType = upIntent.resolveTypeIfNeeded(getContentResolver());
|
||||
return ActivityClient.getInstance().navigateUpTo(mToken, upIntent, resolvedType,
|
||||
resultCode, resultData);
|
||||
} else {
|
||||
return mParent.navigateUpToFromChild(this, upIntent);
|
||||
}
|
||||
|
||||
@@ -141,11 +141,11 @@ public class ActivityClient {
|
||||
}
|
||||
}
|
||||
|
||||
boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
|
||||
boolean navigateUpTo(IBinder token, Intent destIntent, String resolvedType, int resultCode,
|
||||
Intent resultData) {
|
||||
try {
|
||||
return getActivityClientController().navigateUpTo(token, destIntent, resultCode,
|
||||
resultData);
|
||||
return getActivityClientController().navigateUpTo(token, destIntent, resolvedType,
|
||||
resultCode, resultData);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ interface IActivityClientController {
|
||||
in SizeConfigurationBuckets sizeConfigurations);
|
||||
boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot);
|
||||
boolean shouldUpRecreateTask(in IBinder token, in String destAffinity);
|
||||
boolean navigateUpTo(in IBinder token, in Intent target, int resultCode,
|
||||
in Intent resultData);
|
||||
boolean navigateUpTo(in IBinder token, in Intent target, in String resolvedType,
|
||||
int resultCode, in Intent resultData);
|
||||
boolean releaseActivityInstance(in IBinder token);
|
||||
boolean finishActivity(in IBinder token, int code, in Intent data, int finishTask);
|
||||
boolean finishActivityAffinity(in IBinder token);
|
||||
|
||||
@@ -332,8 +332,8 @@ class ActivityClientController extends IActivityClientController.Stub {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
|
||||
Intent resultData) {
|
||||
public boolean navigateUpTo(IBinder token, Intent destIntent, String resolvedType,
|
||||
int resultCode, Intent resultData) {
|
||||
final ActivityRecord r;
|
||||
synchronized (mGlobalLock) {
|
||||
r = ActivityRecord.isInRootTaskLocked(token);
|
||||
@@ -348,7 +348,7 @@ class ActivityClientController extends IActivityClientController.Stub {
|
||||
|
||||
synchronized (mGlobalLock) {
|
||||
return r.getRootTask().navigateUpTo(
|
||||
r, destIntent, destGrants, resultCode, resultData, resultGrants);
|
||||
r, destIntent, resolvedType, destGrants, resultCode, resultData, resultGrants);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5308,8 +5308,9 @@ class Task extends TaskFragment {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean navigateUpTo(ActivityRecord srec, Intent destIntent, NeededUriGrants destGrants,
|
||||
int resultCode, Intent resultData, NeededUriGrants resultGrants) {
|
||||
boolean navigateUpTo(ActivityRecord srec, Intent destIntent, String resolvedType,
|
||||
NeededUriGrants destGrants, int resultCode, Intent resultData,
|
||||
NeededUriGrants resultGrants) {
|
||||
if (!srec.attachedToProcess()) {
|
||||
// Nothing to do if the caller is not attached, because this method should be called
|
||||
// from an alive activity.
|
||||
@@ -5402,28 +5403,22 @@ class Task extends TaskFragment {
|
||||
srec.packageName);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
|
||||
destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS,
|
||||
srec.mUserId);
|
||||
// TODO(b/64750076): Check if calling pid should really be -1.
|
||||
final int res = mAtmService.getActivityStartController()
|
||||
.obtainStarter(destIntent, "navigateUpTo")
|
||||
.setCaller(srec.app.getThread())
|
||||
.setActivityInfo(aInfo)
|
||||
.setResultTo(parent.token)
|
||||
.setCallingPid(-1)
|
||||
.setCallingUid(callingUid)
|
||||
.setCallingPackage(srec.packageName)
|
||||
.setCallingFeatureId(parent.launchedFromFeatureId)
|
||||
.setRealCallingPid(-1)
|
||||
.setRealCallingUid(callingUid)
|
||||
.setComponentSpecified(true)
|
||||
.execute();
|
||||
foundParentInTask = res == ActivityManager.START_SUCCESS;
|
||||
} catch (RemoteException e) {
|
||||
foundParentInTask = false;
|
||||
}
|
||||
// TODO(b/64750076): Check if calling pid should really be -1.
|
||||
final int res = mAtmService.getActivityStartController()
|
||||
.obtainStarter(destIntent, "navigateUpTo")
|
||||
.setResolvedType(resolvedType)
|
||||
.setUserId(srec.mUserId)
|
||||
.setCaller(srec.app.getThread())
|
||||
.setResultTo(parent.token)
|
||||
.setCallingPid(-1)
|
||||
.setCallingUid(callingUid)
|
||||
.setCallingPackage(srec.packageName)
|
||||
.setCallingFeatureId(parent.launchedFromFeatureId)
|
||||
.setRealCallingPid(-1)
|
||||
.setRealCallingUid(callingUid)
|
||||
.setComponentSpecified(true)
|
||||
.execute();
|
||||
foundParentInTask = res == ActivityManager.START_SUCCESS;
|
||||
parent.finishIfPossible(resultCode, resultData, resultGrants,
|
||||
"navigate-top", true /* oomAdj */);
|
||||
}
|
||||
|
||||
@@ -1312,13 +1312,15 @@ public class RootTaskTests extends WindowTestsBase {
|
||||
secondActivity.app.setThread(null);
|
||||
// This should do nothing from a non-attached caller.
|
||||
assertFalse(task.navigateUpTo(secondActivity /* source record */,
|
||||
firstActivity.intent /* destIntent */, null /* destGrants */,
|
||||
0 /* resultCode */, null /* resultData */, null /* resultGrants */));
|
||||
firstActivity.intent /* destIntent */, null /* resolvedType */,
|
||||
null /* destGrants */, 0 /* resultCode */, null /* resultData */,
|
||||
null /* resultGrants */));
|
||||
|
||||
secondActivity.app.setThread(thread);
|
||||
assertTrue(task.navigateUpTo(secondActivity /* source record */,
|
||||
firstActivity.intent /* destIntent */, null /* destGrants */,
|
||||
0 /* resultCode */, null /* resultData */, null /* resultGrants */));
|
||||
firstActivity.intent /* destIntent */, null /* resolvedType */,
|
||||
null /* destGrants */, 0 /* resultCode */, null /* resultData */,
|
||||
null /* resultGrants */));
|
||||
// The firstActivity uses default launch mode, so the activities between it and itself will
|
||||
// be finished.
|
||||
assertTrue(secondActivity.finishing);
|
||||
|
||||
Reference in New Issue
Block a user