From 5451c68cf02d4f3fa9ff169fcc1916930d60eb2b Mon Sep 17 00:00:00 2001 From: James O'Leary Date: Tue, 5 Oct 2021 12:59:26 -0400 Subject: [PATCH] WallpaperManagerService - avoid leaking whether a package is installed An app can detect if an another app is installed, without holding the appropriate permission, due to a difference in control flow. Catching exceptions avoids a difference in control flow, and specifically mitigates the bug report: a SecurityException thrown several steps down the call chain is no longer thrown or logged. The vulnerability took advantage of a difference in control flow in WallpaperManagerService - if the calling app doesn't have the READ_WALLPAPER_INTERNAL permission, WallpaperManagerService then checks if the app has the READ_EXTERNAL_STORAGE/OP_READ_EXTERNAL_STORAGE permission. If the app doesn't, a SecurityException is thrown several levels down the call stack. The malicious app can check the text of that exception, recognize it is a SecurityException, and recognize that the exception text only occurs if there is no installed package name with that package name. Bug: 194105703 Test: Install test APK from Security. Verify it detects Gmail is installed (com.google.android.gm). Apply patch. Verify it can no longer detect Gmail is installed. Change-Id: I4556f6cf367ec8b5a03d04d436dc0b7f93694d3a --- .../server/wallpaper/WallpaperManagerService.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index e190b1e931ed9..c968570221ddb 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -2260,8 +2260,17 @@ public class WallpaperManagerService extends IWallpaperManager.Stub IWallpaperManagerCallback cb, final int which, Bundle outParams, int wallpaperUserId) { final boolean hasPrivilege = hasPermission(READ_WALLPAPER_INTERNAL); if (!hasPrivilege) { - mContext.getSystemService(StorageManager.class).checkPermissionReadImages(true, - Binder.getCallingPid(), Binder.getCallingUid(), callingPkg, callingFeatureId); + try { + mContext.getSystemService(StorageManager.class).checkPermissionReadImages(true, + Binder.getCallingPid(), Binder.getCallingUid(), callingPkg, + callingFeatureId); + } catch (Exception e) { + // If the calling package name does not match a package installed on the system, + // an exception is thrown. Don't allow that exception to be thrown, otherwise, + // there is a difference in control flow that allows calling apps to determine + // if a package is installed on the device. + return null; + } } wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),