Fix crash when startForeground posts a broken Notification.

The NotificationManager tries to crash the calling app, but
in the case of a service calling startForeground, the caller
is the ActivityManager, so system_server goes down.

NotificationManagerService#enqueueNotificationInternal is a
new internal-only method that accepts a UID/PID to use when
punishing bogus notifications (such as the one in
http://b/2869787).

Change-Id: I84a9854bae630bc90288cebb94f174809d5dac8c
This commit is contained in:
Daniel Sandler
2010-08-03 15:29:31 -04:00
parent e339464f1c
commit d0a2f86f35
3 changed files with 26 additions and 11 deletions

View File

@@ -67,7 +67,8 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
class NotificationManagerService extends INotificationManager.Stub
/** {@hide} */
public class NotificationManagerService extends INotificationManager.Stub
{
private static final String TAG = "NotificationService";
private static final boolean DBG = false;
@@ -311,7 +312,8 @@ class NotificationManagerService extends INotificationManager.Stub
public void onNotificationError(String pkg, String tag, int id,
int uid, int initialPid, String message) {
Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id);
Slog.d(TAG, "onNotification error pkg=" + pkg + " tag=" + tag + " id=" + id
+ "; will crashApplication(uid=" + uid + ", pid=" + initialPid + ")");
cancelNotification(pkg, tag, id, 0, 0);
long ident = Binder.clearCallingIdentity();
try {
@@ -666,11 +668,20 @@ class NotificationManagerService extends INotificationManager.Stub
enqueueNotificationWithTag(pkg, null /* tag */, id, notification, idOut);
}
public void enqueueNotificationWithTag(String pkg, String tag, int id,
Notification notification, int[] idOut)
public void enqueueNotificationWithTag(String pkg, String tag, int id, Notification notification,
int[] idOut)
{
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
enqueueNotificationInternal(pkg, Binder.getCallingUid(), Binder.getCallingPid(),
tag, id, notification, idOut);
}
// Not exposed via Binder; for system use only (otherwise malicious apps could spoof the
// uid/pid of another application)
public void enqueueNotificationInternal(String pkg, int callingUid, int callingPid,
String tag, int id, Notification notification, int[] idOut)
{
Slog.d(TAG, "enqueueNotificationWithTag: calling uid=" + callingUid
+ ", pid=" + callingPid);
checkIncomingCall(pkg);