Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33f56060 authored by Felka Chang's avatar Felka Chang
Browse files

Fix sysui's security issue of cross-user copy/paste

Background:
The applications with the granted INTERNAL_SYSTEM_WINDOW and
INTERACT_ACROSS_USERS_FULL means that it could show the same
window for all of users. i.e. to use user 0 presents all of
UI things to all of users.

INTERNAL_SYSTEM_WINDOW usually comes with INTERACT_ACROSS_USERS_FULL
because it will serve all of users to know the information that
comes from framework and system server.

Solution:
Because SystemUI never restarts after the user changing,
ClipboardService can't tell if the callingUid has the the same userId
with the current user or not.  The solution is to use the permission
check. Especially, INTERACT_ACROSS_USERS_FULL and
INTERNAL_SYSTEM_WINDOW. To check INTERACT_ACROSS_USERS_FULL by using
ActivityManagerInternal.handleIncomingUser.

Caution:
The application with INTERNAL_SYSTEM_WINDOW usually use user 0
to show the window. But, the current user is user 10, WindowManager
know the focus windows is belong to user 0 rather user 10. That's
why user 10 can't copy the the text from systemui directly reply to
the other applications.

Readability:
ClipboardService use callingUid everywhere but actaully it is not
appropriated to fix this kind of bug. This patch refactor the naming
to produce two name. i.e. intendingUid and intentdingUserId that are
validated by ActivityManagerInternal.handleIncomingUser.

Test: manual test
Test: atest android.widget.cts.TextViewTest
Test: atest CtsTextTestCases
Test: atest CtsContentTestCases

Bug: 123232892
Bug: 117768051
Change-Id: Ie3daecd1e8fc2f7fdf37baeb5979da9f2e0b3937
parent a35495ff
Loading
Loading
Loading
Loading
+11 −8
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
        try {
            Preconditions.checkNotNull(clip);
            clip.prepareToLeaveProcess(true);
            mService.setPrimaryClip(clip, mContext.getOpPackageName());
            mService.setPrimaryClip(clip, mContext.getOpPackageName(), mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -116,7 +116,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
     */
    public void clearPrimaryClip() {
        try {
            mService.clearPrimaryClip(mContext.getOpPackageName());
            mService.clearPrimaryClip(mContext.getOpPackageName(), mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -132,7 +132,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
     */
    public @Nullable ClipData getPrimaryClip() {
        try {
            return mService.getPrimaryClip(mContext.getOpPackageName());
            return mService.getPrimaryClip(mContext.getOpPackageName(), mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -149,7 +149,8 @@ public class ClipboardManager extends android.text.ClipboardManager {
     */
    public @Nullable ClipDescription getPrimaryClipDescription() {
        try {
            return mService.getPrimaryClipDescription(mContext.getOpPackageName());
            return mService.getPrimaryClipDescription(mContext.getOpPackageName(),
                    mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -163,7 +164,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
     */
    public boolean hasPrimaryClip() {
        try {
            return mService.hasPrimaryClip(mContext.getOpPackageName());
            return mService.hasPrimaryClip(mContext.getOpPackageName(), mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
@@ -174,7 +175,8 @@ public class ClipboardManager extends android.text.ClipboardManager {
            if (mPrimaryClipChangedListeners.isEmpty()) {
                try {
                    mService.addPrimaryClipChangedListener(
                            mPrimaryClipChangedServiceListener, mContext.getOpPackageName());
                            mPrimaryClipChangedServiceListener, mContext.getOpPackageName(),
                            mContext.getUserId());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
@@ -189,7 +191,8 @@ public class ClipboardManager extends android.text.ClipboardManager {
            if (mPrimaryClipChangedListeners.isEmpty()) {
                try {
                    mService.removePrimaryClipChangedListener(
                            mPrimaryClipChangedServiceListener);
                            mPrimaryClipChangedServiceListener, mContext.getOpPackageName(),
                            mContext.getUserId());
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
@@ -226,7 +229,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
    @Deprecated
    public boolean hasText() {
        try {
            return mService.hasClipboardText(mContext.getOpPackageName());
            return mService.hasClipboardText(mContext.getOpPackageName(), mContext.getUserId());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+9 −8
Original line number Diff line number Diff line
@@ -26,17 +26,18 @@ import android.content.IOnPrimaryClipChangedListener;
 * {@hide}
 */
interface IClipboard {
    void setPrimaryClip(in ClipData clip, String callingPackage);
    void clearPrimaryClip(String callingPackage);
    ClipData getPrimaryClip(String pkg);
    ClipDescription getPrimaryClipDescription(String callingPackage);
    boolean hasPrimaryClip(String callingPackage);
    void setPrimaryClip(in ClipData clip, String callingPackage, int userId);
    void clearPrimaryClip(String callingPackage, int userId);
    ClipData getPrimaryClip(String pkg, int userId);
    ClipDescription getPrimaryClipDescription(String callingPackage, int userId);
    boolean hasPrimaryClip(String callingPackage, int userId);
    void addPrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener,
            String callingPackage);
    void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener);
            String callingPackage, int userId);
    void removePrimaryClipChangedListener(in IOnPrimaryClipChangedListener listener,
            String callingPackage, int userId);

    /**
     * Returns true if the clipboard contains text; false otherwise.
     */
    boolean hasClipboardText(String callingPackage);
    boolean hasClipboardText(String callingPackage, int userId);
}
+18 −13
Original line number Diff line number Diff line
@@ -11244,13 +11244,23 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    @Nullable
    final TextServicesManager getTextServicesManagerForUser() {
        return getServiceManagerForUser("android", TextServicesManager.class);
    }
    @Nullable
    final ClipboardManager getClipboardManagerForUser() {
        return getServiceManagerForUser(getContext().getPackageName(), ClipboardManager.class);
    }
    @Nullable
    final <T> T getServiceManagerForUser(String packageName, Class<T> managerClazz) {
        if (mTextOperationUser == null) {
            return getContext().getSystemService(TextServicesManager.class);
            return getContext().getSystemService(managerClazz);
        }
        try {
            return getContext().createPackageContextAsUser(
                    "android", 0 /* flags */, mTextOperationUser)
                    .getSystemService(TextServicesManager.class);
            Context context = getContext().createPackageContextAsUser(
                    packageName, 0 /* flags */, mTextOperationUser);
            return context.getSystemService(managerClazz);
        } catch (PackageManager.NameNotFoundException e) {
            return null;
        }
@@ -12540,8 +12550,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                && mEditor != null && mEditor.mKeyListener != null
                && getSelectionStart() >= 0
                && getSelectionEnd() >= 0
                && ((ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE))
                        .hasPrimaryClip());
                && getClipboardManagerForUser().hasPrimaryClip());
    }
    boolean canPasteAsPlainText() {
@@ -12549,9 +12558,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            return false;
        }
        final ClipData clipData =
                ((ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE))
                        .getPrimaryClip();
        final ClipData clipData = getClipboardManagerForUser().getPrimaryClip();
        final ClipDescription description = clipData.getDescription();
        final boolean isPlainType = description.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN);
        final CharSequence text = clipData.getItemAt(0).getText();
@@ -12594,8 +12601,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
     * Paste clipboard content between min and max positions.
     */
    private void paste(int min, int max, boolean withFormatting) {
        ClipboardManager clipboard =
                (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
        ClipboardManager clipboard = getClipboardManagerForUser();
        ClipData clip = clipboard.getPrimaryClip();
        if (clip != null) {
            boolean didFirst = false;
@@ -12638,8 +12644,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    @CheckResult
    private boolean setPrimaryClip(ClipData clip) {
        ClipboardManager clipboard =
                (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
        ClipboardManager clipboard = getClipboardManagerForUser();
        try {
            clipboard.setPrimaryClip(clip);
        } catch (Throwable t) {
+181 −58

File changed.

Preview size limit exceeded, changes collapsed.