Allow 2-pane deep link to access unexported Activity

If an Activity is not exported, the Activity still can be
launched by components of the same application, applications
with the same user ID, or privileged system components.

Bug: 261678674
Bug: 250589026
Test: manual visual
      Launcher -> context menu -> Wallpaper & style
Change-Id: I662df6cb287361b135e2c596abe946ddeb03bda4
Merged-In: I662df6cb287361b135e2c596abe946ddeb03bda4
This commit is contained in:
Arc Wang
2022-12-12 14:44:16 +08:00
parent 1c6313d8c0
commit f964b68fee

View File

@@ -32,6 +32,8 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo; import android.content.pm.UserInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.text.TextUtils; import android.text.TextUtils;
@@ -448,20 +450,19 @@ public class SettingsHomepageActivity extends FragmentActivity implements
return; return;
} }
if (!TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()), ActivityInfo targetActivityInfo = null;
getPackageName())) { try {
ActivityInfo targetActivityInfo = null; targetActivityInfo = getPackageManager().getActivityInfo(targetComponentName,
try { /* flags= */ 0);
targetActivityInfo = getPackageManager().getActivityInfo(targetComponentName, } catch (PackageManager.NameNotFoundException e) {
/* flags= */ 0); Log.e(TAG, "Failed to get target ActivityInfo: " + e);
} catch (PackageManager.NameNotFoundException e) { finish();
Log.e(TAG, "Failed to get target ActivityInfo: " + e); return;
finish(); }
return;
}
if (!hasPrivilegedAccess(targetActivityInfo)) {
if (!targetActivityInfo.exported) { if (!targetActivityInfo.exported) {
Log.e(TAG, "Must not launch an unexported Actvity for deep link"); Log.e(TAG, "Target Activity is not exported");
finish(); finish();
return; return;
} }
@@ -514,6 +515,46 @@ public class SettingsHomepageActivity extends FragmentActivity implements
} }
} }
// Check if calling app has privileged access to launch Activity of activityInfo.
private boolean hasPrivilegedAccess(ActivityInfo activityInfo) {
if (TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()),
getPackageName())) {
return true;
}
int callingUid = -1;
try {
callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken());
} catch (RemoteException re) {
Log.e(TAG, "Not able to get callingUid: " + re);
return false;
}
int targetUid = -1;
try {
targetUid = getPackageManager().getApplicationInfo(activityInfo.packageName,
/* flags= */ 0).uid;
} catch (PackageManager.NameNotFoundException nnfe) {
Log.e(TAG, "Not able to get targetUid: " + nnfe);
return false;
}
// When activityInfo.exported is false, Activity still can be launched if applications have
// the same user ID.
if (UserHandle.isSameApp(callingUid, targetUid)) {
return true;
}
// When activityInfo.exported is false, Activity still can be launched if calling app has
// root or system privilege.
int callingAppId = UserHandle.getAppId(callingUid);
if (callingAppId == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID) {
return true;
}
return false;
}
@VisibleForTesting @VisibleForTesting
boolean isCallingAppPermitted(String permission) { boolean isCallingAppPermitted(String permission) {
return TextUtils.isEmpty(permission) || PasswordUtils.isCallingAppPermitted( return TextUtils.isEmpty(permission) || PasswordUtils.isCallingAppPermitted(