Loading src/com/android/launcher3/InstallShortcutReceiver.java +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } Loading src/com/android/launcher3/Launcher.java +17 −2 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.TestingUtils; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.PendingAddWidgetInfo; Loading Loading @@ -191,6 +192,8 @@ public class Launcher extends Activity private static final String RUNTIME_STATE_PENDING_ADD_SPAN_X = "launcher.add_span_x"; // Type: int private static final String RUNTIME_STATE_PENDING_ADD_SPAN_Y = "launcher.add_span_y"; // Type: int private static final String RUNTIME_STATE_PENDING_ADD_COMPONENT = "launcher.add_component"; // Type: parcelable private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_INFO = "launcher.add_widget_info"; // Type: parcelable Loading Loading @@ -242,7 +245,7 @@ public class Launcher extends Activity private AppWidgetManagerCompat mAppWidgetManager; private LauncherAppWidgetHost mAppWidgetHost; @Thunk ItemInfo mPendingAddInfo = new ItemInfo(); @Thunk PendingAddItemInfo mPendingAddInfo = new PendingAddItemInfo(); private LauncherAppWidgetProviderInfo mPendingAddWidgetInfo; private int mPendingAddWidgetId = -1; Loading Loading @@ -1312,6 +1315,8 @@ public class Launcher extends Activity mPendingAddInfo.cellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y); mPendingAddInfo.spanX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X); mPendingAddInfo.spanY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y); mPendingAddInfo.componentName = savedState.getParcelable(RUNTIME_STATE_PENDING_ADD_COMPONENT); AppWidgetProviderInfo info = savedState.getParcelable( RUNTIME_STATE_PENDING_ADD_WIDGET_INFO); mPendingAddWidgetInfo = info == null ? Loading Loading @@ -1499,7 +1504,13 @@ public class Launcher extends Activity CellLayout layout = getCellLayout(container, screenId); ShortcutInfo info = InstallShortcutReceiver.fromShortcutIntent(this, data); if (info == null) { if (info == null || mPendingAddInfo.componentName == null) { return; } if (!PackageManagerHelper.hasPermissionForActivity( this, info.intent, mPendingAddInfo.componentName.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); Loading Loading @@ -1966,6 +1977,8 @@ public class Launcher extends Activity outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mPendingAddInfo.cellY); outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_X, mPendingAddInfo.spanX); outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y, mPendingAddInfo.spanY); outState.putParcelable(RUNTIME_STATE_PENDING_ADD_COMPONENT, mPendingAddInfo.componentName); outState.putParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO, mPendingAddWidgetInfo); outState.putInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID, mPendingAddWidgetId); } Loading Loading @@ -2198,6 +2211,7 @@ public class Launcher extends Activity mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1; mPendingAddInfo.minSpanX = mPendingAddInfo.minSpanY = 1; mPendingAddInfo.dropPos = null; mPendingAddInfo.componentName = null; } void addAppWidgetFromDropImpl(final int appWidgetId, final ItemInfo info, final Loading Loading @@ -2273,6 +2287,7 @@ public class Launcher extends Activity mPendingAddInfo.container = container; mPendingAddInfo.screenId = screenId; mPendingAddInfo.dropPos = null; mPendingAddInfo.componentName = componentName; if (cell != null) { mPendingAddInfo.cellX = cell[0]; Loading src/com/android/launcher3/util/PackageManagerHelper.java +56 −0 Original line number Diff line number Diff line Loading @@ -16,8 +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; Loading Loading @@ -68,4 +75,53 @@ public class PackageManagerHelper { return false; } } /** * 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; } } Loading
src/com/android/launcher3/InstallShortcutReceiver.java +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } } Loading
src/com/android/launcher3/Launcher.java +17 −2 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ import com.android.launcher3.compat.UserManagerCompat; import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.TestingUtils; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.PendingAddWidgetInfo; Loading Loading @@ -191,6 +192,8 @@ public class Launcher extends Activity private static final String RUNTIME_STATE_PENDING_ADD_SPAN_X = "launcher.add_span_x"; // Type: int private static final String RUNTIME_STATE_PENDING_ADD_SPAN_Y = "launcher.add_span_y"; // Type: int private static final String RUNTIME_STATE_PENDING_ADD_COMPONENT = "launcher.add_component"; // Type: parcelable private static final String RUNTIME_STATE_PENDING_ADD_WIDGET_INFO = "launcher.add_widget_info"; // Type: parcelable Loading Loading @@ -242,7 +245,7 @@ public class Launcher extends Activity private AppWidgetManagerCompat mAppWidgetManager; private LauncherAppWidgetHost mAppWidgetHost; @Thunk ItemInfo mPendingAddInfo = new ItemInfo(); @Thunk PendingAddItemInfo mPendingAddInfo = new PendingAddItemInfo(); private LauncherAppWidgetProviderInfo mPendingAddWidgetInfo; private int mPendingAddWidgetId = -1; Loading Loading @@ -1312,6 +1315,8 @@ public class Launcher extends Activity mPendingAddInfo.cellY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_CELL_Y); mPendingAddInfo.spanX = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_X); mPendingAddInfo.spanY = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y); mPendingAddInfo.componentName = savedState.getParcelable(RUNTIME_STATE_PENDING_ADD_COMPONENT); AppWidgetProviderInfo info = savedState.getParcelable( RUNTIME_STATE_PENDING_ADD_WIDGET_INFO); mPendingAddWidgetInfo = info == null ? Loading Loading @@ -1499,7 +1504,13 @@ public class Launcher extends Activity CellLayout layout = getCellLayout(container, screenId); ShortcutInfo info = InstallShortcutReceiver.fromShortcutIntent(this, data); if (info == null) { if (info == null || mPendingAddInfo.componentName == null) { return; } if (!PackageManagerHelper.hasPermissionForActivity( this, info.intent, mPendingAddInfo.componentName.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); Loading Loading @@ -1966,6 +1977,8 @@ public class Launcher extends Activity outState.putInt(RUNTIME_STATE_PENDING_ADD_CELL_Y, mPendingAddInfo.cellY); outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_X, mPendingAddInfo.spanX); outState.putInt(RUNTIME_STATE_PENDING_ADD_SPAN_Y, mPendingAddInfo.spanY); outState.putParcelable(RUNTIME_STATE_PENDING_ADD_COMPONENT, mPendingAddInfo.componentName); outState.putParcelable(RUNTIME_STATE_PENDING_ADD_WIDGET_INFO, mPendingAddWidgetInfo); outState.putInt(RUNTIME_STATE_PENDING_ADD_WIDGET_ID, mPendingAddWidgetId); } Loading Loading @@ -2198,6 +2211,7 @@ public class Launcher extends Activity mPendingAddInfo.spanX = mPendingAddInfo.spanY = -1; mPendingAddInfo.minSpanX = mPendingAddInfo.minSpanY = 1; mPendingAddInfo.dropPos = null; mPendingAddInfo.componentName = null; } void addAppWidgetFromDropImpl(final int appWidgetId, final ItemInfo info, final Loading Loading @@ -2273,6 +2287,7 @@ public class Launcher extends Activity mPendingAddInfo.container = container; mPendingAddInfo.screenId = screenId; mPendingAddInfo.dropPos = null; mPendingAddInfo.componentName = componentName; if (cell != null) { mPendingAddInfo.cellX = cell[0]; Loading
src/com/android/launcher3/util/PackageManagerHelper.java +56 −0 Original line number Diff line number Diff line Loading @@ -16,8 +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; Loading Loading @@ -68,4 +75,53 @@ public class PackageManagerHelper { return false; } } /** * 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; } }