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
This commit is contained in:
James O'Leary
2021-10-05 12:59:26 -04:00
parent 1d3b8a30a4
commit 5451c68cf0

View File

@@ -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(),