Improve package visibility gap for TextServicesManager
Two APIs in TextServicesManager expose the installed spell checker packages to the caller without holding the query package permission. - getSpellCheckerService - getEnabledSpellCheckers This cl filter the access to spell checkers from the caller by rules of package visibilty. Bug: 212287294 Bug: 212287061 Test: atest CtsAppEnumerationTestCases Test: atest android.view.inputmethod.cts.SpellCheckerTest Change-Id: I109231ca438db3a1df95a54322548bb11c026a78
This commit is contained in:
@@ -303,6 +303,10 @@ public final class TextServicesManager {
|
||||
/**
|
||||
* Retrieve the list of currently enabled spell checkers.
|
||||
*
|
||||
* <p> Note: The results are filtered by the rules of
|
||||
* <a href="/training/basics/intents/package-visibility">package visibility</a>, except for
|
||||
* the currently active spell checker.
|
||||
*
|
||||
* @return The list of currently enabled spell checkers.
|
||||
*/
|
||||
@UserHandleAware
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManagerInternal;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
@@ -583,10 +584,17 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
|
||||
return;
|
||||
}
|
||||
final SpellCheckerInfo sci = spellCheckerMap.get(sciId);
|
||||
final int uid = Binder.getCallingUid();
|
||||
if (!canCallerAccessSpellChecker(sci, uid, userId)) {
|
||||
if (DBG) {
|
||||
Slog.d(TAG, "Spell checker " + sci.getId()
|
||||
+ " is not visible to the caller " + uid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
HashMap<String, SpellCheckerBindGroup> spellCheckerBindGroups =
|
||||
tsd.mSpellCheckerBindGroups;
|
||||
SpellCheckerBindGroup bindGroup = spellCheckerBindGroups.get(sciId);
|
||||
final int uid = Binder.getCallingUid();
|
||||
if (bindGroup == null) {
|
||||
final long ident = Binder.clearCallingIdentity();
|
||||
try {
|
||||
@@ -649,20 +657,28 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
|
||||
public SpellCheckerInfo[] getEnabledSpellCheckers(@UserIdInt int userId) {
|
||||
verifyUser(userId);
|
||||
|
||||
final ArrayList<SpellCheckerInfo> spellCheckerList;
|
||||
synchronized (mLock) {
|
||||
final TextServicesData tsd = getDataFromCallingUserIdLocked(userId);
|
||||
if (tsd == null) return null;
|
||||
|
||||
ArrayList<SpellCheckerInfo> spellCheckerList = tsd.mSpellCheckerList;
|
||||
if (DBG) {
|
||||
Slog.d(TAG, "getEnabledSpellCheckers: " + spellCheckerList.size());
|
||||
for (int i = 0; i < spellCheckerList.size(); ++i) {
|
||||
Slog.d(TAG,
|
||||
"EnabledSpellCheckers: " + spellCheckerList.get(i).getPackageName());
|
||||
}
|
||||
}
|
||||
return spellCheckerList.toArray(new SpellCheckerInfo[spellCheckerList.size()]);
|
||||
spellCheckerList = new ArrayList<>(tsd.mSpellCheckerList);
|
||||
}
|
||||
int size = spellCheckerList.size();
|
||||
final int callingUid = Binder.getCallingUid();
|
||||
for (int i = size - 1; i >= 0; i--) {
|
||||
if (canCallerAccessSpellChecker(spellCheckerList.get(i), callingUid, userId)) {
|
||||
continue;
|
||||
}
|
||||
if (DBG) {
|
||||
Slog.d(TAG, "Spell checker " + spellCheckerList.get(i).getPackageName()
|
||||
+ " is not visible to the caller " + callingUid);
|
||||
}
|
||||
spellCheckerList.remove(i);
|
||||
}
|
||||
|
||||
return spellCheckerList.isEmpty() ? null
|
||||
: spellCheckerList.toArray(new SpellCheckerInfo[spellCheckerList.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -701,6 +717,26 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the access to spell checkers by rules of the package visibility. Return {@code true}
|
||||
* if the given spell checker is the currently selected one or visible to the caller.
|
||||
*
|
||||
* @param sci The spell checker to check.
|
||||
* @param callingUid The caller that is going to access the spell checker.
|
||||
* @param userId The user id where the spell checker resides.
|
||||
* @return {@code true} if caller is able to access the spell checker.
|
||||
*/
|
||||
private boolean canCallerAccessSpellChecker(@NonNull SpellCheckerInfo sci, int callingUid,
|
||||
@UserIdInt int userId) {
|
||||
final SpellCheckerInfo currentSci = getCurrentSpellCheckerForUser(userId);
|
||||
if (currentSci != null && currentSci.getId().equals(sci.getId())) {
|
||||
return true;
|
||||
}
|
||||
final PackageManagerInternal pmInternal =
|
||||
LocalServices.getService(PackageManagerInternal.class);
|
||||
return !pmInternal.filterAppAccess(sci.getPackageName(), callingUid, userId);
|
||||
}
|
||||
|
||||
private void setCurrentSpellCheckerLocked(@Nullable SpellCheckerInfo sci, TextServicesData tsd) {
|
||||
final String sciId = (sci != null) ? sci.getId() : "";
|
||||
if (DBG) {
|
||||
|
||||
Reference in New Issue
Block a user