mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-03 17:36:49 +00:00
Preventing a shortcut which requires permissions from being added to
homescreen A shortcut can be added by any app as INSTALL_SHORTCUT is a normal level permission. But the intent is actually launched by the launcher app which can have other permission as well. > When adding a shortcut from the broadcast, verify that the intent does not require any permission > When adding a shortcut using the two-step drop process, verify that the source app also has the permission to create such a shortcut Bug: 30778130 Change-Id: I710a490d69019dc25709db5a97020c20d9325007
This commit is contained in:
@@ -33,6 +33,7 @@ import com.android.launcher3.compat.LauncherActivityInfoCompat;
|
||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.util.Thunk;
|
||||
|
||||
import org.json.JSONException;
|
||||
@@ -146,6 +147,15 @@ public class InstallShortcutReceiver extends BroadcastReceiver {
|
||||
}
|
||||
PendingInstallShortcutInfo info = createPendingInfo(context, data);
|
||||
if (info != null) {
|
||||
if (!info.isLauncherActivity()) {
|
||||
// Since its a custom shortcut, verify that it is safe to launch.
|
||||
if (!PackageManagerHelper.hasPermissionForActivity(
|
||||
context, info.launchIntent, null)) {
|
||||
// Target cannot be launched, or requires some special permission to launch
|
||||
Log.e(TAG, "Ignoring malicious intent " + info.launchIntent.toUri(0));
|
||||
return;
|
||||
}
|
||||
}
|
||||
queuePendingShortcutInfo(info, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,7 +652,7 @@ public class Launcher extends Activity
|
||||
|
||||
switch (requestCode) {
|
||||
case REQUEST_CREATE_SHORTCUT:
|
||||
completeAddShortcut(intent, info.container, screenId, info.cellX, info.cellY);
|
||||
completeAddShortcut(intent, info.container, screenId, info.cellX, info.cellY, info);
|
||||
break;
|
||||
case REQUEST_CREATE_APPWIDGET:
|
||||
completeAddAppWidget(appWidgetId, info, null, null);
|
||||
@@ -1456,12 +1456,19 @@ public class Launcher extends Activity
|
||||
* @param data The intent describing the shortcut.
|
||||
*/
|
||||
private void completeAddShortcut(Intent data, long container, long screenId, int cellX,
|
||||
int cellY) {
|
||||
int cellY, PendingRequestArgs args) {
|
||||
int[] cellXY = mTmpAddItemCellCoordinates;
|
||||
CellLayout layout = getCellLayout(container, screenId);
|
||||
|
||||
ShortcutInfo info = InstallShortcutReceiver.fromShortcutIntent(this, data);
|
||||
if (info == null) {
|
||||
if (info == null || args.getRequestCode() != REQUEST_CREATE_SHORTCUT ||
|
||||
args.getPendingIntent().getComponent() == null) {
|
||||
return;
|
||||
}
|
||||
if (!PackageManagerHelper.hasPermissionForActivity(
|
||||
this, info.intent, args.getPendingIntent().getComponent().getPackageName())) {
|
||||
// The app is trying to add a shortcut without sufficient permissions
|
||||
Log.e(TAG, "Ignoring malicious intent " + info.intent.toUri(0));
|
||||
return;
|
||||
}
|
||||
final View view = createShortcut(info);
|
||||
@@ -2178,10 +2185,9 @@ public class Launcher extends Activity
|
||||
* Process a shortcut drop.
|
||||
*/
|
||||
private void processShortcutFromDrop(PendingAddItemInfo info) {
|
||||
setWaitingForResult(new PendingRequestArgs(info));
|
||||
Intent createShortcutIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
|
||||
createShortcutIntent.setComponent(info.componentName);
|
||||
Utilities.startActivityForResultSafely(this, createShortcutIntent, REQUEST_CREATE_SHORTCUT);
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_SHORTCUT).setComponent(info.componentName);
|
||||
setWaitingForResult(PendingRequestArgs.forIntent(REQUEST_CREATE_SHORTCUT, intent, info));
|
||||
Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_SHORTCUT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,10 +16,15 @@
|
||||
|
||||
package com.android.launcher3.util;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
|
||||
@@ -96,4 +101,53 @@ public class PackageManagerHelper {
|
||||
}
|
||||
return excludePackages.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if {@param srcPackage} has the permission required to start the activity from
|
||||
* {@param intent}. If {@param srcPackage} is null, then the activity should not need
|
||||
* any permissions
|
||||
*/
|
||||
public static boolean hasPermissionForActivity(Context context, Intent intent,
|
||||
String srcPackage) {
|
||||
PackageManager pm = context.getPackageManager();
|
||||
ResolveInfo target = pm.resolveActivity(intent, 0);
|
||||
if (target == null) {
|
||||
// Not a valid target
|
||||
return false;
|
||||
}
|
||||
if (TextUtils.isEmpty(target.activityInfo.permission)) {
|
||||
// No permission is needed
|
||||
return true;
|
||||
}
|
||||
if (TextUtils.isEmpty(srcPackage)) {
|
||||
// The activity requires some permission but there is no source.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Source does not have sufficient permissions.
|
||||
if(pm.checkPermission(target.activityInfo.permission, srcPackage) !=
|
||||
PackageManager.PERMISSION_GRANTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Utilities.ATLEAST_MARSHMALLOW) {
|
||||
// These checks are sufficient for below M devices.
|
||||
return true;
|
||||
}
|
||||
|
||||
// On M and above also check AppOpsManager for compatibility mode permissions.
|
||||
if (TextUtils.isEmpty(AppOpsManager.permissionToOp(target.activityInfo.permission))) {
|
||||
// There is no app-op for this permission, which could have been disabled.
|
||||
return true;
|
||||
}
|
||||
|
||||
// There is no direct way to check if the app-op is allowed for a particular app. Since
|
||||
// app-op is only enabled for apps running in compatibility mode, simply block such apps.
|
||||
|
||||
try {
|
||||
return pm.getApplicationInfo(srcPackage, 0).targetSdkVersion >= Build.VERSION_CODES.M;
|
||||
} catch (NameNotFoundException e) { }
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user