summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yohei Yukawa <yukawa@google.com> 2019-01-22 00:00:53 -0800
committer Yohei Yukawa <yukawa@google.com> 2019-01-22 00:00:53 -0800
commit716897ce2ee155b3bda109bc5092b142fd63c350 (patch)
treedc18611a01a23d2d7ff501de2fd3f089697d255a
parent3dc172438a3b45160f3c95eb202ea39c1ba2b348 (diff)
Harden caller verification in IMMS#startInputOrWindowGainedFocus()
Previously, privileged processes (w/ INTERACT_ACROSS_USERS_FULL) that run as user X are automatically allowed to connect to the current IME even when it runs as a different user Y. However, as explained in my previous CL [1], there are many text operations that are already fully multiuser-aware hence need to be connected to the right user's services. If EditorInfo#targetInputMethodUser [2] is not correctly set when it should have been, it's highly likely that the IME client would need to call TextView#setTextOperationUser() [3] as I did for System UI [1]. To detect such problems as early as possible, with this CL IMMS#startInputOrWindowGainedFocus() no longer resolves null EditorInfo#targetInputMethodUser as the current IME user for privileged processes that have INTERACT_ACROSS_USERS_FULL permission. If this CL broke some IME use case, most likely the IME client app would need to be fixed. [1]: Ibabe13e5b85e5bb91f9f8af6ec07c395c25c4393 7276946b92fbac928b1d34971b9c4ffd975d95e4 [2]: Ia7ea944438d69669ccdf9111b34ba400e786a602 0f5eade4a492fc91130da1aedcad0999932f4137 [3]: I6d11e4d6a84570bc2991a8552349e8b216b0d139 401e3d4c842ce86569de4477138137dc07a6aa6f Bug: 34886274 Test: atest CtsInputMethodTestCases CtsInputMethodServiceHostTestCases Test: per-profile mode still works. Test: Manually tested multi-user scenario as follows 1. Build and flash an AOSP build 2. Create a secondary user then switch to it. 3. make -j SoftKeyboard 4. adb install -r $OUT/system/app/SoftKeyboard/SoftKeyboard.apk 5. adb shell ime enable com.example.android.softkeyboard/.SoftKeyboard 6. adb shell ime set com.example.android.softkeyboard/.SoftKeyboard 7. make -j EditTextVariations 8. adb install -r $ANDROID_TARGET_OUT_TESTCASES/EditTextVariations/EditTextVariations.apk 9. adb shell am start \ -n com.android.inputmethod.tools.edittextvariations/.EditTextVariations 10. Tap the menu icon on the EditTextVariations then click "Direct Reply" 11. Tap reply icon on "Message from UserHandle{10}". 12. Make sure that SoftKeyboard Sample IME is shown. 13. Type "ggggg" then hit the space key. 14. Make sure that red underline is drawn under "ggggg" 15. Make sure that AndroidSpellCheckerService runs as user 10. 16. Set up a text screenlock. 17. Turn off the display. 18. Turn on the display. 19. Make sure that SoftKeyboard Sample IME is shown. Change-Id: Ieb94ed14698ee2669adc5fb2ea0e93c7d0e09e8b
-rw-r--r--core/java/android/view/inputmethod/EditorInfo.java10
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java13
2 files changed, 9 insertions, 14 deletions
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index f99afe6cdab9..8e7b0db21946 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -479,13 +479,9 @@ public class EditorInfo implements InputType, Parcelable {
* If not {@code null}, this editor needs to talk to IMEs that run for the specified user, no
* matter what user ID the calling process has.
*
- * <p>Note: This field is silently ignored when:</p>
- * <ul>
- * <li>{@link android.view.inputmethod.InputMethodSystemProperty#PER_PROFILE_IME_ENABLED} is
- * {@code false}.</li>
- * <li>{@link android.view.inputmethod.InputMethodSystemProperty#MULTI_CLIENT_IME_ENABLED}
- * is {@code true}.</li>
- * </ul>
+ * <p>Note: This field will be silently ignored when
+ * {@link android.view.inputmethod.InputMethodSystemProperty#MULTI_CLIENT_IME_ENABLED} is
+ * {@code true}.</p>
*
* <p>Note also that pseudo handles such as {@link UserHandle#ALL} are not supported.</p>
*
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 6c3cc58a1bd6..2d197bb4da96 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2845,7 +2845,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
int unverifiedTargetSdkVersion) {
final int callingUserId = UserHandle.getCallingUserId();
final int userId;
- if (PER_PROFILE_IME_ENABLED && attribute != null && attribute.targetInputMethodUser != null
+ if (attribute != null && attribute.targetInputMethodUser != null
&& attribute.targetInputMethodUser.getIdentifier() != callingUserId) {
mContext.enforceCallingPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL,
"Using EditorInfo.user requires INTERACT_ACROSS_USERS_FULL.");
@@ -2862,9 +2862,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
InputBindResult res = null;
synchronized (mMethodMap) {
- // Needs to check the validity before clearing calling identity
- // Note that cross-profile access is always allowed here to allow profile-switching.
- final boolean calledFromValidUser = calledFromValidUserLocked(true);
final int windowDisplayId =
mWindowManagerInternal.getDisplayIdForWindow(windowToken);
final long ident = Binder.clearCallingIdentity();
@@ -2908,10 +2905,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return InputBindResult.NOT_IME_TARGET_WINDOW;
}
- if (!calledFromValidUser) {
+ // cross-profile access is always allowed here to allow profile-switching.
+ if (!mSettings.isCurrentProfile(userId)) {
Slog.w(TAG, "A background user is requesting window. Hiding IME.");
- Slog.w(TAG, "If you want to interect with IME, you need "
- + "android.permission.INTERACT_ACROSS_USERS_FULL");
+ Slog.w(TAG, "If you need to impersonate a foreground user/profile from"
+ + " a background user, use EditorInfo.targetInputMethodUser with"
+ + " INTERACT_ACROSS_USERS_FULL permission.");
hideCurrentInputLocked(0, null);
return InputBindResult.INVALID_USER;
}