diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2016-09-08 14:32:06 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2016-09-08 14:41:01 -0700 |
commit | fb5096d07bb3bb59fd4b5db6b68613030169b4bd (patch) | |
tree | 3f7fb4506c460b632563f7cbe30222b8633486b3 /src/com/android | |
parent | add78abb98391ccd74b96e1e4d312e3c89fe0eba (diff) | |
download | android_packages_apps_Trebuchet-fb5096d07bb3bb59fd4b5db6b68613030169b4bd.tar.gz android_packages_apps_Trebuchet-fb5096d07bb3bb59fd4b5db6b68613030169b4bd.tar.bz2 android_packages_apps_Trebuchet-fb5096d07bb3bb59fd4b5db6b68613030169b4bd.zip |
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
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/launcher3/InstallShortcutReceiver.java | 10 | ||||
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 20 | ||||
-rw-r--r-- | src/com/android/launcher3/util/PackageManagerHelper.java | 54 |
3 files changed, 77 insertions, 7 deletions
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java index df87cc204..d8e58d829 100644 --- a/src/com/android/launcher3/InstallShortcutReceiver.java +++ b/src/com/android/launcher3/InstallShortcutReceiver.java @@ -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); } } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 901900e0f..07c290377 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -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); } /** diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java index 3c4c79aec..3e15d05e1 100644 --- a/src/com/android/launcher3/util/PackageManagerHelper.java +++ b/src/com/android/launcher3/util/PackageManagerHelper.java @@ -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; + } } |