From ac094513e0af65b081be3b0334b0046ba80dfd92 Mon Sep 17 00:00:00 2001 From: Farid Zare Seisan Date: Mon, 2 Apr 2018 15:06:13 -0700 Subject: [PATCH] Ignore mkdirs requests if CE storage not available. There is a time gap between user unlock and CE storage preparation. This would creates a race between thread preparing CE storages and another thread doing a mkdirs. An application call to getExternalCacheDir() result in a mkdirs call. mkdirs would create a full path inside CE directory. If directories are created before encryption policies are applied then CE storage preparation would fail on the very first boot. This will cause the device to not ever boot successfully. This change will prevent an app from breaking the system. Another solution would have been moving CE preparation inside user unlock before updating mLocalUnlockedUsers, that would guarantee that CE storage is ready when isUserKeyUnlocked returns true, but that would be riskier change. Bug: 76222913 Test: No longer can break CE preparation by calling getExternalCacheDir() early. Change-Id: I3141f541b43bb51a444f8c79b63e5a6d4b3fd3b2 (cherry picked from commit 4d24d8130b7fdbe46751f527d615143f4cb4de4b) --- .../java/com/android/server/StorageManagerService.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java index 379658f6302f9..99e0459d5d23c 100644 --- a/services/core/java/com/android/server/StorageManagerService.java +++ b/services/core/java/com/android/server/StorageManagerService.java @@ -2667,9 +2667,17 @@ class StorageManagerService extends IStorageManager.Stub public void mkdirs(String callingPkg, String appPath) { final int userId = UserHandle.getUserId(Binder.getCallingUid()); final UserEnvironment userEnv = new UserEnvironment(userId); + final String propertyName = "sys.user." + userId + ".ce_available"; // Ignore requests to create directories while storage is locked - if (!isUserKeyUnlocked(userId)) return; + if (!isUserKeyUnlocked(userId)) { + throw new IllegalStateException("Failed to prepare " + appPath); + } + + // Ignore requests to create directories if CE storage is not available + if (!SystemProperties.getBoolean(propertyName, false)) { + throw new IllegalStateException("Failed to prepare " + appPath); + } // Validate that reported package name belongs to caller final AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(