diff options
author | Dianne Hackborn <hackbod@google.com> | 2013-03-25 17:49:36 -0700 |
---|---|---|
committer | Paul Kocialkowski <contact@paulk.fr> | 2015-08-25 18:12:59 +0200 |
commit | a6de323672a3d3e3e5510cf47a4cd1d61118ba98 (patch) | |
tree | a80dff589f3b34e77974aba91db02bbfcd079e27 /services | |
parent | be640cae67b534624d6b45b71bb43f25f8f84226 (diff) | |
download | frameworks_base-a6de323672a3d3e3e5510cf47a4cd1d61118ba98.zip frameworks_base-a6de323672a3d3e3e5510cf47a4cd1d61118ba98.tar.gz frameworks_base-a6de323672a3d3e3e5510cf47a4cd1d61118ba98.tar.bz2 |
Fix issue #8470131: Process thrash kills battery
Protect app widget broadcasts from abuse.
In this case the app was sending an APPWIDGET_UPDATE broadcast
without specifying a target, which (a) should not be allowed (you
should not be able to send updates to other apps), and (b) resulted
in every single potential app widget in the system being launched...
which was about 75 of them.
Change-Id: I9d48733610ce6d5a7c32e69a3e06b9f33bd79a34
Signed-off-by: Dianne Hackborn <hackbod@google.com>
Tested-by: Moritz Bandemer <replicant@posteo.mx>
Diffstat (limited to 'services')
3 files changed, 36 insertions, 2 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 4c83116..dc4661f 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -19,6 +19,7 @@ package com.android.server.am; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import android.appwidget.AppWidgetManager; import com.android.internal.R; import com.android.internal.app.ThemeUtils; import com.android.internal.os.BatteryStatsImpl; @@ -11737,6 +11738,32 @@ public final class ActivityManagerService extends ActivityManagerNative + callingPid + ", uid=" + callingUid; Slog.w(TAG, msg); throw new SecurityException(msg); + } else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(intent.getAction())) { + // Special case for compatibility: we don't want apps to send this, + // but historically it has not been protected and apps may be using it + // to poke their own app widget. So, instead of making it protected, + // just limit it to the caller. + if (callerApp == null) { + String msg = "Permission Denial: not allowed to send broadcast " + + intent.getAction() + " from unknown caller."; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } else if (intent.getComponent() != null) { + // They are good enough to send to an explicit component... verify + // it is being sent to the calling app. + if (!intent.getComponent().getPackageName().equals( + callerApp.info.packageName)) { + String msg = "Permission Denial: not allowed to send broadcast " + + intent.getAction() + " to " + + intent.getComponent().getPackageName() + " from " + + callerApp.info.packageName; + Slog.w(TAG, msg); + throw new SecurityException(msg); + } + } else { + // Limit broadcast to their own package. + intent.setPackage(callerApp.info.packageName); + } } } catch (RemoteException e) { Slog.w(TAG, "Remote exception", e); diff --git a/services/java/com/android/server/am/BroadcastQueue.java b/services/java/com/android/server/am/BroadcastQueue.java index fc4ecda..468fd17 100644 --- a/services/java/com/android/server/am/BroadcastQueue.java +++ b/services/java/com/android/server/am/BroadcastQueue.java @@ -29,7 +29,6 @@ import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.content.pm.ServiceInfo; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -1071,6 +1070,9 @@ public class BroadcastQueue { pw.print(" #"); pw.print(i); pw.print(": "); pw.println(r); pw.print(" "); pw.println(r.intent.toShortString(false, true, true, false)); + if (r.targetComp != null && r.targetComp != r.intent.getComponent()) { + pw.print(" targetComp: "); pw.println(r.targetComp.toShortString()); + } Bundle bundle = r.intent.getExtras(); if (bundle != null) { pw.print(" extras: "); pw.println(bundle.toString()); diff --git a/services/java/com/android/server/am/BroadcastRecord.java b/services/java/com/android/server/am/BroadcastRecord.java index 1cf5b9c..ce14074 100644 --- a/services/java/com/android/server/am/BroadcastRecord.java +++ b/services/java/com/android/server/am/BroadcastRecord.java @@ -37,6 +37,7 @@ import java.util.List; */ class BroadcastRecord extends Binder { final Intent intent; // the original intent that generated us + final ComponentName targetComp; // original component name set on the intent final ProcessRecord callerApp; // process that sent this final String callerPackage; // who sent this final int callingPid; // the pid of who sent this @@ -82,9 +83,12 @@ class BroadcastRecord extends Binder { pw.print(prefix); pw.print(this); pw.print(" to user "); pw.println(userId); pw.print(prefix); pw.println(intent.toInsecureString()); + if (targetComp != null && targetComp != intent.getComponent()) { + pw.print(prefix); pw.print(" targetComp: "); pw.println(targetComp.toShortString()); + } Bundle bundle = intent.getExtras(); if (bundle != null) { - pw.print(prefix); pw.print("extras: "); pw.println(bundle.toString()); + pw.print(prefix); pw.print(" extras: "); pw.println(bundle.toString()); } pw.print(prefix); pw.print("caller="); pw.print(callerPackage); pw.print(" "); pw.print(callerApp != null ? callerApp.toShortString() : "null"); @@ -171,6 +175,7 @@ class BroadcastRecord extends Binder { int _userId) { queue = _queue; intent = _intent; + targetComp = _intent.getComponent(); callerApp = _callerApp; callerPackage = _callerPackage; callingPid = _callingPid; |