From f1c31a5d4d4f13e3249cac825f8e22c8904aaadb Mon Sep 17 00:00:00 2001 From: LuK1337 Date: Thu, 2 Feb 2017 11:26:12 +0100 Subject: Use STREAM_RING on non-voice capable devices * That's what Google does. Change-Id: Iac88d161eb1dccbbb5c538d5e04d8d1fc43edef2 --- services/core/java/com/android/server/audio/AudioService.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'services') diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index fe3df61..7b90c83 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1101,10 +1101,13 @@ public class AudioService extends IAudioService.Stub { mStreamVolumeAlias[AudioSystem.STREAM_DTMF] = dtmfStreamAlias; - if (mLinkNotificationWithVolume && mVoiceCapable) { - mStreamVolumeAlias[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING; - } else { - mStreamVolumeAlias[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_NOTIFICATION; + if (mVoiceCapable) { + if (mLinkNotificationWithVolume) { + mStreamVolumeAlias[AudioSystem.STREAM_NOTIFICATION] = AudioSystem.STREAM_RING; + } else { + mStreamVolumeAlias[AudioSystem.STREAM_NOTIFICATION] = + AudioSystem.STREAM_NOTIFICATION; + } } if (updateVolumes) { -- cgit v1.1 From ca7312891adcdfc300f2b5c07222120de52030ea Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 16 Nov 2016 17:22:48 -0700 Subject: DO NOT MERGE: Check provider access for content changes. For an app to either send or receive content change notifications, require that they have some level of access to the underlying provider. Without these checks, a malicious app could sniff sensitive user data from the notifications of otherwise private providers. Test: builds, boots, PoC app now fails Bug: 32555637 Change-Id: If2dcd45cb0a9f1fb3b93e39fc7b8ae9c34c2fdef (cherry picked from commit c813f5dae231bd8f01864227c5dba10d43a89249) (cherry picked from commit db57376d6ccbd4d3e39fc35aa8cfb561bbca4bac) mh0rst: Backport from android-7.1.1_r21 --- .../android/server/am/ActivityManagerService.java | 43 ++++++++++++ .../com/android/server/content/ContentService.java | 79 +++++++++++++--------- 2 files changed, 91 insertions(+), 31 deletions(-) (limited to 'services') diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 23f34e6..317dea4 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9623,6 +9623,44 @@ public final class ActivityManagerService extends ActivityManagerNative } /** + * Check if the calling UID has a possible chance at accessing the provider + * at the given authority and user. + */ + public String checkContentProviderAccess(String authority, int userId) { + if (userId == UserHandle.USER_ALL) { + mContext.enforceCallingOrSelfPermission( + Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); + userId = UserHandle.getCallingUserId(); + } + + ProviderInfo cpi = null; + try { + cpi = AppGlobals.getPackageManager().resolveContentProvider(authority, + STOCK_PM_FLAGS | PackageManager.GET_URI_PERMISSION_PATTERNS, + userId); + } catch (RemoteException ignored) { + } + if (cpi == null) { + // TODO: make this an outright failure in a future platform release; + // until then anonymous content notifications are unprotected + //return "Failed to find provider " + authority + " for user " + userId; + return null; + } + + ProcessRecord r = null; + synchronized (mPidsSelfLocked) { + r = mPidsSelfLocked.get(Binder.getCallingPid()); + } + if (r == null) { + return "Failed to find PID " + Binder.getCallingPid(); + } + + synchronized (this) { + return checkContentProviderPermissionLocked(cpi, r, userId, true); + } + } + + /** * Check if {@link ProcessRecord} has a possible chance at accessing the * given {@link ProviderInfo}. Final permission checking is always done * in {@link ContentProvider}. @@ -21136,6 +21174,11 @@ public final class ActivityManagerService extends ActivityManagerNative private final class LocalService extends ActivityManagerInternal { @Override + public String checkContentProviderAccess(String authority, int userId) { + return ActivityManagerService.this.checkContentProviderAccess(authority, userId); + } + + @Override public void onWakefulnessChanged(int wakefulness) { ActivityManagerService.this.onWakefulnessChanged(wakefulness); } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index f581a7f..1db31c9 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -19,6 +19,8 @@ package com.android.server.content; import android.Manifest; import android.accounts.Account; import android.app.ActivityManager; +import android.app.ActivityManagerInternal; +import android.app.ActivityManagerNative; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; @@ -51,7 +53,6 @@ import com.android.server.LocalServices; import java.io.FileDescriptor; import java.io.PrintWriter; -import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -190,23 +191,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); - final int callingUserHandle = UserHandle.getCallingUserId(); - // Registering an observer for any user other than the calling user requires uri grant or - // cross user permission - if (callingUserHandle != userHandle && - mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_READ_URI_PERMISSION) - != PackageManager.PERMISSION_GRANTED) { - enforceCrossUserPermission(userHandle, - "no permission to observe other users' provider view"); - } - if (userHandle < 0) { - if (userHandle == UserHandle.USER_CURRENT) { - userHandle = ActivityManager.getCurrentUser(); - } else if (userHandle != UserHandle.USER_ALL) { - throw new InvalidParameterException("Bad user handle for registerContentObserver: " - + userHandle); - } + userHandle = handleIncomingUser(uri, pid, uid, + Intent.FLAG_GRANT_READ_URI_PERMISSION, userHandle); + + final String msg = LocalServices.getService(ActivityManagerInternal.class) + .checkContentProviderAccess(uri.getAuthority(), userHandle); + if (msg != null) { + Log.w(TAG, "Ignoring content changes for " + uri + " from " + uid + ": " + msg); + return; } synchronized (mRootNode) { @@ -253,21 +246,15 @@ public final class ContentService extends IContentService.Stub { final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); final int callingUserHandle = UserHandle.getCallingUserId(); - // Notify for any user other than the caller requires uri grant or cross user permission - if (callingUserHandle != userHandle && - mContext.checkUriPermission(uri, pid, uid, Intent.FLAG_GRANT_WRITE_URI_PERMISSION) - != PackageManager.PERMISSION_GRANTED) { - enforceCrossUserPermission(userHandle, "no permission to notify other users"); - } - // We passed the permission check; resolve pseudouser targets as appropriate - if (userHandle < 0) { - if (userHandle == UserHandle.USER_CURRENT) { - userHandle = ActivityManager.getCurrentUser(); - } else if (userHandle != UserHandle.USER_ALL) { - throw new InvalidParameterException("Bad user handle for notifyChange: " - + userHandle); - } + userHandle = handleIncomingUser(uri, pid, uid, + Intent.FLAG_GRANT_WRITE_URI_PERMISSION, userHandle); + + final String msg = LocalServices.getService(ActivityManagerInternal.class) + .checkContentProviderAccess(uri.getAuthority(), userHandle); + if (msg != null) { + Log.w(TAG, "Ignoring notify for " + uri + " from " + uid + ": " + msg); + return; } // This makes it so that future permission checks will be in the context of this @@ -317,6 +304,15 @@ public final class ContentService extends IContentService.Stub { } } + private int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, int userHandle) { + try { + return ActivityManagerNative.getDefault().checkUriPermission( + uri, pid, uid, modeFlags, userHandle, null); + } catch (RemoteException e) { + return PackageManager.PERMISSION_DENIED; + } + } + public void notifyChange(Uri uri, IContentObserver observer, boolean observerWantsSelfNotifications, boolean syncToNetwork) { notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork, @@ -924,6 +920,27 @@ public final class ContentService extends IContentService.Stub { return service; } + private int handleIncomingUser(Uri uri, int pid, int uid, int modeFlags, int userId) { + if (userId == UserHandle.USER_CURRENT) { + userId = ActivityManager.getCurrentUser(); + } + + if (userId == UserHandle.USER_ALL) { + mContext.enforceCallingOrSelfPermission( + Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); + } else if (userId < 0) { + throw new IllegalArgumentException("Invalid user: " + userId); + } else if (userId != UserHandle.getCallingUserId()) { + if (checkUriPermission(uri, pid, uid, modeFlags, + userId) != PackageManager.PERMISSION_GRANTED) { + mContext.enforceCallingOrSelfPermission( + Manifest.permission.INTERACT_ACROSS_USERS_FULL, TAG); + } + } + + return userId; + } + /** * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS_FULL * permission, if the userHandle is not for the caller. -- cgit v1.1 From 44b0bdc995fbc21b294e1cdca3a5aa63feeb4951 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Wed, 30 Nov 2016 16:07:00 -0700 Subject: DO NOT MERGE. Retain DownloadManager Uri grants when clearing. As part of fixing a recent security issue, DownloadManager now needs to issue Uri permission grants for all downloads. However, if an app that requested a download is upgraded or otherwise force-stopped, the required permission grants are removed. We could tell DownloadManager about the app being stopped, but that would be racy (due to background broadcast), and waking it up would degrade system health. Instead, as a special case we now only consider clearing DownloadManager permission grants when app data is being cleared. Bug: 32172542, 30537115 Test: builds, boots, app upgrade doesn't clear grants Change-Id: I7e3d4546fd12bfe5f81b9fb9857ece58d574a6b9 (cherry picked from commit 23ec811266fb728cf159a90ce4882b3c9bac1887) (cherry picked from commit 6eee8e37fd06bd47dd19b8503bc30cc8ccaf72a7) (cherry picked from commit 36772fc2263e06972add737660392afd246da15e) --- .../core/java/com/android/server/am/ActivityManagerService.java | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'services') diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 317dea4..3715620 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -219,6 +219,7 @@ import android.os.UpdateLock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.provider.Downloads; import android.telecom.TelecomManager; import android.text.format.DateUtils; import android.text.format.Time; @@ -8181,6 +8182,12 @@ public final class ActivityManagerService extends ActivityManagerNative // Only inspect grants matching package if (packageName == null || perm.sourcePkg.equals(packageName) || perm.targetPkg.equals(packageName)) { + // Hacky solution as part of fixing a security bug; ignore + // grants associated with DownloadManager so we don't have + // to immediately launch it to regrant the permissions + if (Downloads.Impl.AUTHORITY.equals(perm.uri.uri.getAuthority()) + && !persistable) continue; + persistChanged |= perm.revokeModes(persistable ? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION, true); -- cgit v1.1 From 2ffca13ae484c15087ddd14f69d3e593b51fc904 Mon Sep 17 00:00:00 2001 From: Charles He Date: Thu, 24 Nov 2016 14:05:00 +0000 Subject: Prevent writing to FRP partition during factory reset. Avoid potential race condition between FRP wipe and write operations during factory reset by making the FRP partition unwritable after wipe. Bug: 30352311 Test: manual CVE-2017-0498 Change-Id: If3f024a1611366c0677a996705724458094fcfad (cherry picked from commit a629c772f4a7a5ddf7ff9f78fb19f7ab86c2a9c2) (cherry picked from commit a9437bd1caeeb38780d920a81bde8cc7ca280fe0) (cherry picked from commit 1c4d535d0806dbeb6d2fa5cea0373cbd9ab6d33b) --- .../android/server/PersistentDataBlockService.java | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'services') diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java index 94316fe..32b183b 100644 --- a/services/core/java/com/android/server/PersistentDataBlockService.java +++ b/services/core/java/com/android/server/PersistentDataBlockService.java @@ -50,15 +50,14 @@ import java.util.Arrays; * This data will live across factory resets not initiated via the Settings UI. * When a device is factory reset through Settings this data is wiped. * - * Allows writing one block at a time. Namely, each time - * {@link android.service.persistentdata.IPersistentDataBlockService}.write(byte[] data) - * is called, it will overwite the data that was previously written on the block. + * Allows writing one block at a time. Namely, each time {@link IPersistentDataBlockService#write} + * is called, it will overwrite the data that was previously written on the block. * * Clients can query the size of the currently written block via - * {@link android.service.persistentdata.IPersistentDataBlockService}.getTotalDataSize(). + * {@link IPersistentDataBlockService#getDataBlockSize} * - * Clients can any number of bytes from the currently written block up to its total size by invoking - * {@link android.service.persistentdata.IPersistentDataBlockService}.read(byte[] data) + * Clients can read any number of bytes from the currently written block up to its total size by + * invoking {@link IPersistentDataBlockService#read} */ public class PersistentDataBlockService extends SystemService { private static final String TAG = PersistentDataBlockService.class.getSimpleName(); @@ -78,6 +77,7 @@ public class PersistentDataBlockService extends SystemService { private int mAllowedUid = -1; private long mBlockDeviceSize; + private boolean mIsWritable = true; public PersistentDataBlockService(Context context) { super(context); @@ -349,6 +349,11 @@ public class PersistentDataBlockService extends SystemService { headerAndData.put(data); synchronized (mLock) { + if (!mIsWritable) { + IoUtils.closeQuietly(outputStream); + return -1; + } + try { byte[] checksum = new byte[DIGEST_SIZE_BYTES]; outputStream.write(checksum, 0, DIGEST_SIZE_BYTES); @@ -423,6 +428,9 @@ public class PersistentDataBlockService extends SystemService { if (ret < 0) { Slog.e(TAG, "failed to wipe persistent partition"); + } else { + mIsWritable = false; + Slog.i(TAG, "persistent partition now wiped and unwritable"); } } } -- cgit v1.1 From 4f1644e029bddd02b633c4f66801b73c26316361 Mon Sep 17 00:00:00 2001 From: Charles He Date: Thu, 1 Dec 2016 19:22:33 +0000 Subject: Add @GuardedBy annotation to PersistentDataBlockService#mIsWritable. Test: manual Bug: 30352311 CVE-2017-0498 Change-Id: I1024f2a56badde5c123d025d6fe02f42559cbcb1 (cherry picked from commit f6f1d627483b4dad9d65176769a1ee92c59a4810) (cherry picked from commit 71d2a41dd9c8be8c4bca5eba339802e1e0c2be3c) (cherry picked from commit 5f621b5b1549e8379aee05807652d5111382ccc6) --- services/core/java/com/android/server/PersistentDataBlockService.java | 3 +++ 1 file changed, 3 insertions(+) (limited to 'services') diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java index 32b183b..9346083 100644 --- a/services/core/java/com/android/server/PersistentDataBlockService.java +++ b/services/core/java/com/android/server/PersistentDataBlockService.java @@ -29,6 +29,7 @@ import android.service.persistentdata.IPersistentDataBlockService; import android.util.Slog; import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; import libcore.io.IoUtils; @@ -77,6 +78,8 @@ public class PersistentDataBlockService extends SystemService { private int mAllowedUid = -1; private long mBlockDeviceSize; + + @GuardedBy("mLock") private boolean mIsWritable = true; public PersistentDataBlockService(Context context) { -- cgit v1.1 From e53c4cb312e5bd0f5ef8415a6c476e59f060b639 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 16 Jan 2017 10:49:55 -0800 Subject: Fixed the logic for tethering provisioning re-evaluation Previously we only re-evaluate provisioning for SIM swap case The new logic covers both SIM swap case (ABSENT->NOT_READY->UNKNOWN->READY->LOADED) and modem reset case (NOT_READY->READY->LOADED) Test: Manual bug: 33815946 Merged-In: I9960123605b10d3fa5f3584c6c8b70b616acd6f8 AOSP-Change-Id: I9960123605b10d3fa5f3584c6c8b70b616acd6f8 CVE-2017-0554 Change-Id: I5d55db56b61780eb83e57bc021d36a129416ce5c (cherry picked from commit 3294256ba5b9e2ba2d8619d617e3d900e5386564) --- .../java/com/android/server/connectivity/Tethering.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'services') diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 60d6772..873e0c3 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -1696,9 +1696,8 @@ public class Tethering extends BaseNetworkObserver { // used to verify this receiver is still current final private int mGenerationNumber; - // we're interested in edge-triggered LOADED notifications, so - // ignore LOADED unless we saw an ABSENT state first - private boolean mSimAbsentSeen = false; + // used to check the sim state transition from non-loaded to loaded + private boolean mSimNotLoadedSeen = false; public SimChangeBroadcastReceiver(int generationNumber) { super(); @@ -1716,14 +1715,14 @@ public class Tethering extends BaseNetworkObserver { final String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); - Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" + - mSimAbsentSeen); - if (!mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) { - mSimAbsentSeen = true; + Log.d(TAG, "got Sim changed to state " + state + ", mSimNotLoadedSeen=" + + mSimNotLoadedSeen); + if (!mSimNotLoadedSeen && !IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { + mSimNotLoadedSeen = true; } - if (mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { - mSimAbsentSeen = false; + if (mSimNotLoadedSeen && IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) { + mSimNotLoadedSeen = false; try { if (mContext.getResources().getString(com.android.internal.R.string. config_mobile_hotspot_provision_app_no_ui).isEmpty() == false) { -- cgit v1.1 From d81dca8b1a4786940cfcb8c7aeba72ab541bd58a Mon Sep 17 00:00:00 2001 From: Makoto Onuki Date: Wed, 4 Jan 2017 14:36:59 -0800 Subject: Do not call RecoverySystem with DPMS lock held Note DPM.wipeData() on a secondary user is now blocking, just like it's been always blocking on the primary user. Test: Manually tested wipeData() with ApiDemos, both on 1) the primary user, 2) a secondary user and 3) work profile. Test: adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest -w com.android.frameworks.servicestests Bug 30681079 AOSP-Change-Id: Ia832bed0f22396998d6307ab46e262dae9463838 Merged-in: Ib97a92a6af87a5589d2643b9ae0522395735e1a5 CVE-2017-0560 Change-Id: Icc6a5e655ed184e2a386e79bd5cf2c231f22e403 (cherry picked from commit efdec8f5688ce6b0a287eddb6d5dad93ffa0e1ee) --- .../devicepolicy/DevicePolicyManagerService.java | 60 ++++++++++++---------- 1 file changed, 33 insertions(+), 27 deletions(-) (limited to 'services') diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 302d23a..911862e 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -3322,7 +3322,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } - private void wipeDataLocked(boolean wipeExtRequested, String reason) { + private void wipeDataNoLock(boolean wipeExtRequested, String reason) { if (wipeExtRequested) { StorageManager sm = (StorageManager) mContext.getSystemService( Context.STORAGE_SERVICE); @@ -3341,13 +3341,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } enforceCrossUserPermission(userHandle); + + final String source; synchronized (this) { // This API can only be called by an active device admin, // so try to retrieve it to check that the caller is one. final ActiveAdmin admin = getActiveAdminForCallerLocked(null, DeviceAdminInfo.USES_POLICY_WIPE_DATA); - final String source; final ComponentName cname = admin.info.getComponent(); if (cname != null) { source = cname.flattenToShortString(); @@ -3372,39 +3373,44 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { manager.wipe(); } } - boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0; - wipeDeviceOrUserLocked(wipeExtRequested, userHandle, - "DevicePolicyManager.wipeData() from " + source); } finally { Binder.restoreCallingIdentity(ident); } } + final boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0; + wipeDeviceNoLock(wipeExtRequested, userHandle, + "DevicePolicyManager.wipeData() from " + source); } - private void wipeDeviceOrUserLocked(boolean wipeExtRequested, final int userHandle, String reason) { - if (userHandle == UserHandle.USER_OWNER) { - wipeDataLocked(wipeExtRequested, reason); - } else { - mHandler.post(new Runnable() { - @Override - public void run() { - try { - IActivityManager am = ActivityManagerNative.getDefault(); - if (am.getCurrentUser().id == userHandle) { - am.switchUser(UserHandle.USER_OWNER); - } + private void wipeDeviceNoLock(boolean wipeExtRequested, final int userHandle, String reason) { + final long ident = Binder.clearCallingIdentity(); + try { + if (userHandle == UserHandle.USER_OWNER) { + wipeDataNoLock(wipeExtRequested, reason); + } else { + mHandler.post(new Runnable() { + @Override + public void run() { + try { + IActivityManager am = ActivityManagerNative.getDefault(); + if (am.getCurrentUser().id == userHandle) { + am.switchUser(UserHandle.USER_OWNER); + } - boolean isManagedProfile = isManagedProfile(userHandle); - if (!mUserManager.removeUser(userHandle)) { - Slog.w(LOG_TAG, "Couldn't remove user " + userHandle); - } else if (isManagedProfile) { - sendWipeProfileNotification(); + boolean isManagedProfile = isManagedProfile(userHandle); + if (!mUserManager.removeUser(userHandle)) { + Slog.w(LOG_TAG, "Couldn't remove user " + userHandle); + } else if (isManagedProfile) { + sendWipeProfileNotification(); + } + } catch (RemoteException re) { + // Shouldn't happen } - } catch (RemoteException re) { - // Shouldn't happen } - } - }); + }); + } + } finally { + Binder.restoreCallingIdentity(ident); } } @@ -3562,7 +3568,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } if (wipeData) { // Call without holding lock. - wipeDeviceOrUserLocked(false, identifier, + wipeDeviceNoLock(false, identifier, "reportFailedPasswordAttempt()"); } } finally { -- cgit v1.1 From 51d0b0fc52891ec3714c5bb4fedd9f1598e0224c Mon Sep 17 00:00:00 2001 From: Tom O'Neill Date: Thu, 22 Dec 2016 17:59:47 +0000 Subject: Fix exploit where can hide the fact that a location was mocked am: a206a0f17e am: d417e54872 am: 3380a77516 am: 0a8978f04b am: 1684e5f344 am: d28eef0cc2 am: 1f458fdc66 am: d82f8a67fc am: 1ac8affd51 am: 56098f81b6 am: 7cec76de0f am: 2da05d0f9e AOSP-Change-Id: I8c94a06f5fa722312436484609bafcb0585d6d18 CVE-2017-0489 Change-Id: I7bf939b05b7bfc5a855b212fe8c92fc58943e7d6 (cherry picked from commit d22261fef84481651e12995062105239d551cbc6) --- .../java/com/android/server/LocationManagerService.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'services') diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index 6cd8e10..5019161 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -88,6 +88,8 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.WorkSource; import android.provider.Settings; +import android.text.TextUtils; +import android.util.EventLog; import android.util.Log; import android.util.Slog; @@ -2638,9 +2640,22 @@ public class LocationManagerService extends ILocationManager.Stub { if (mockProvider == null) { throw new IllegalArgumentException("Provider \"" + provider + "\" unknown"); } + + // Ensure that the location is marked as being mock. There's some logic to do this in + // handleLocationChanged(), but it fails if loc has the wrong provider (bug 33091107). + Location mock = new Location(loc); + mock.setIsFromMockProvider(true); + + if (!TextUtils.isEmpty(loc.getProvider()) && !provider.equals(loc.getProvider())) { + // The location has an explicit provider that is different from the mock provider + // name. The caller may be trying to fool us via bug 33091107. + EventLog.writeEvent(0x534e4554, "33091107", Binder.getCallingUid(), + provider + "!=" + loc.getProvider()); + } + // clear calling identity so INSTALL_LOCATION_PROVIDER permission is not required long identity = Binder.clearCallingIdentity(); - mockProvider.setLocation(loc); + mockProvider.setLocation(mock); Binder.restoreCallingIdentity(identity); } } -- cgit v1.1