From c4291b920f86660d8878839184116170c18c72f4 Mon Sep 17 00:00:00 2001 From: Cassie Wang Date: Mon, 1 Feb 2021 16:39:37 -0800 Subject: [PATCH] Require unlocked user for AppSearchImpl. Enforce that we'll only create an AppSearchImpl/IcingSearchEngine instance for unlocked users. If we see an unknown user id, throw a SecurityException. This is so that we don't accidentally write data to a non-credential-encrypted storage. Bug: 179406838 Test: atest FrameworksServicesTests Change-Id: If5d1bf35a3f9fa514a42a1d152ac8d88f963ca1f --- .../appsearch/AppSearchManagerService.java | 30 +++++++++++++++++++ .../server/appsearch/ImplInstanceManager.java | 4 +-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java index 3bbc945c8b87b..271129bee7c56 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java @@ -38,6 +38,7 @@ import android.os.ParcelableException; import android.os.RemoteException; import android.os.UserHandle; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import com.android.internal.util.Preconditions; @@ -49,6 +50,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; /** TODO(b/142567528): add comments when implement this class */ public class AppSearchManagerService extends SystemService { @@ -56,6 +58,9 @@ public class AppSearchManagerService extends SystemService { private PackageManagerInternal mPackageManagerInternal; private ImplInstanceManager mImplInstanceManager; + // Cache of unlocked user ids so we don't have to query UserManager service each time. + private final Set mUnlockedUserIds = new ArraySet<>(); + public AppSearchManagerService(Context context) { super(context); } @@ -67,6 +72,11 @@ public class AppSearchManagerService extends SystemService { mImplInstanceManager = ImplInstanceManager.getInstance(getContext()); } + @Override + public void onUserUnlocked(@NonNull TargetUser user) { + mUnlockedUserIds.add(user.getUserIdentifier()); + } + private class Stub extends IAppSearchManager.Stub { @Override public void setSchema( @@ -86,6 +96,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); verifyCallingPackage(callingUid, packageName); List schemas = new ArrayList<>(schemaBundles.size()); for (int i = 0; i < schemaBundles.size(); i++) { @@ -133,6 +144,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); verifyCallingPackage(callingUid, packageName); AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(getContext(), callingUserId); @@ -165,6 +177,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); verifyCallingPackage(callingUid, packageName); AppSearchBatchResult.Builder resultBuilder = new AppSearchBatchResult.Builder<>(); @@ -207,6 +220,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); verifyCallingPackage(callingUid, packageName); AppSearchBatchResult.Builder resultBuilder = new AppSearchBatchResult.Builder<>(); @@ -253,6 +267,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); verifyCallingPackage(callingUid, packageName); AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(getContext(), callingUserId); @@ -287,6 +302,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); verifyCallingPackage(callingUid, packageName); AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(getContext(), callingUserId); @@ -318,6 +334,7 @@ public class AppSearchManagerService extends SystemService { // TODO(b/162450968) check nextPageToken is being advanced by the same uid as originally // opened it try { + verifyUserUnlocked(callingUserId); AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(getContext(), callingUserId); SearchResultPage searchResultPage = impl.getNextPage(nextPageToken); @@ -337,6 +354,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(getContext(), callingUserId); impl.invalidateNextPageToken(nextPageToken); @@ -364,6 +382,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(getContext(), callingUserId); impl.reportUsage(packageName, databaseName, namespace, uri, usageTimeMillis); @@ -392,6 +411,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); verifyCallingPackage(callingUid, packageName); AppSearchBatchResult.Builder resultBuilder = new AppSearchBatchResult.Builder<>(); @@ -431,6 +451,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); verifyCallingPackage(callingUid, packageName); AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(getContext(), callingUserId); @@ -453,6 +474,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); AppSearchImpl impl = mImplInstanceManager.getAppSearchImpl(getContext(), callingUserId); impl.persistToDisk(); @@ -470,6 +492,7 @@ public class AppSearchManagerService extends SystemService { int callingUserId = handleIncomingUser(userId, callingUid); final long callingIdentity = Binder.clearCallingIdentity(); try { + verifyUserUnlocked(callingUserId); mImplInstanceManager.getAppSearchImpl(getContext(), callingUserId); invokeCallbackOnResult(callback, AppSearchResult.newSuccessfulResult(null)); } catch (Throwable t) { @@ -479,6 +502,13 @@ public class AppSearchManagerService extends SystemService { } } + private void verifyUserUnlocked(int callingUserId) { + if (!mUnlockedUserIds.contains(callingUserId)) { + throw new IllegalStateException( + "User " + callingUserId + " is locked or not running."); + } + } + private void verifyCallingPackage(int callingUid, @NonNull String callingPackage) { Preconditions.checkNotNull(callingPackage); if (mPackageManagerInternal.getPackageUid( diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java index 97b1a8cd6d50b..5ea2a02b5b404 100644 --- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java +++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java @@ -73,8 +73,8 @@ public final class ImplInstanceManager { /** * Gets an instance of AppSearchImpl for the given user. * - *

If no AppSearchImpl instance exists for this user, Icing will be initialized and one will - * be created. + *

If no AppSearchImpl instance exists for the unlocked user, Icing will be initialized and + * one will be created. * * @param context The context * @param userId The multi-user userId of the device user calling AppSearch