diff options
| author | 2018-04-09 22:24:22 +0000 | |
|---|---|---|
| committer | 2018-04-09 22:24:22 +0000 | |
| commit | 1890afd456cd6fa182aeeb5efacf159c1115d5ef (patch) | |
| tree | f1808254a99a72f0c5ae77db0f5701f82c4a7191 | |
| parent | 20a5009e2347e45aafba29b9661bbf870adceddb (diff) | |
| parent | 5ddeef71166872ac55b32ed11bc6ed8e4222fbdc (diff) | |
[automerger] RESTRICT AUTOMERGE: Prevent reporting fake package name - framework (backport to nyc-dev) am: 33c37cb37c am: 93d9547b61 am: 5ddeef7116
Change-Id: Ib3a14de258a548393279940fd3aeb067f2596ca8
9 files changed, 365 insertions, 117 deletions
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl index 81cddbac3f53..f138ddb037f0 100644 --- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl +++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl @@ -35,22 +35,22 @@ interface IAccessibilityServiceConnection { void setServiceInfo(in AccessibilityServiceInfo info); - boolean findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId, + String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, long threadId); - boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, + String[] findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId); - boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId, + String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId, long accessibilityNodeId, String viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId); - boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, + String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId); - boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, + String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId); boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, diff --git a/core/java/android/appwidget/AppWidgetManagerInternal.java b/core/java/android/appwidget/AppWidgetManagerInternal.java new file mode 100644 index 000000000000..daa297de8727 --- /dev/null +++ b/core/java/android/appwidget/AppWidgetManagerInternal.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.appwidget; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.util.ArraySet; + +import java.util.Set; + +/** + * App widget manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class AppWidgetManagerInternal { + + /** + * Gets the packages from which the uid hosts widgets. + * + * @param uid The potential host UID. + * @return Whether the UID hosts widgets from the package. + */ + public abstract @Nullable ArraySet<String> getHostedWidgetPackages(int uid); +} diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java index b3f44536214b..5fce1a8d388f 100644 --- a/core/java/android/os/UserHandle.java +++ b/core/java/android/os/UserHandle.java @@ -156,6 +156,11 @@ public final class UserHandle implements Parcelable { } /** @hide */ + public static @AppIdInt int getCallingAppId() { + return getAppId(Binder.getCallingUid()); + } + + /** @hide */ @SystemApi public static UserHandle of(@UserIdInt int userId) { return userId == USER_SYSTEM ? SYSTEM : new UserHandle(userId); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index f761b9b4ea14..ac5a5db3f47c 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -7295,6 +7295,7 @@ public final class ViewRootImpl implements ViewParent, if (!registered) { mAttachInfo.mAccessibilityWindowId = mAccessibilityManager.addAccessibilityInteractionConnection(mWindow, + mContext.getPackageName(), new AccessibilityInteractionConnection(ViewRootImpl.this)); } } diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java index 1406fbd9d074..7b40bf964b7d 100644 --- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java +++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java @@ -28,6 +28,8 @@ import android.util.Log; import android.util.LongSparseArray; import android.util.SparseArray; +import com.android.internal.util.ArrayUtils; + import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -283,16 +285,23 @@ public final class AccessibilityInteractionClient } final int interactionId = mInteractionIdCounter.getAndIncrement(); final long identityToken = Binder.clearCallingIdentity(); - final boolean success = connection.findAccessibilityNodeInfoByAccessibilityId( - accessibilityWindowId, accessibilityNodeId, interactionId, this, - prefetchFlags, Thread.currentThread().getId()); - Binder.restoreCallingIdentity(identityToken); - // If the scale is zero the call has failed. - if (success) { + final String[] packageNames; + try { + packageNames = connection.findAccessibilityNodeInfoByAccessibilityId( + accessibilityWindowId, accessibilityNodeId, interactionId, this, + prefetchFlags, Thread.currentThread().getId()); + } finally { + Binder.restoreCallingIdentity(identityToken); + } + if (packageNames != null) { List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); - finalizeAndCacheAccessibilityNodeInfos(infos, connectionId); + finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, + bypassCache, packageNames); if (infos != null && !infos.isEmpty()) { + for (int i = 1; i < infos.size(); i++) { + infos.get(i).recycle(); + } return infos.get(0); } } @@ -331,15 +340,21 @@ public final class AccessibilityInteractionClient if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final long identityToken = Binder.clearCallingIdentity(); - final boolean success = connection.findAccessibilityNodeInfosByViewId( - accessibilityWindowId, accessibilityNodeId, viewId, interactionId, this, - Thread.currentThread().getId()); - Binder.restoreCallingIdentity(identityToken); - if (success) { + final String[] packageNames; + try { + packageNames = connection.findAccessibilityNodeInfosByViewId( + accessibilityWindowId, accessibilityNodeId, viewId, interactionId, this, + Thread.currentThread().getId()); + } finally { + Binder.restoreCallingIdentity(identityToken); + } + + if (packageNames != null) { List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); if (infos != null) { - finalizeAndCacheAccessibilityNodeInfos(infos, connectionId); + finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, + false, packageNames); return infos; } } @@ -379,15 +394,21 @@ public final class AccessibilityInteractionClient if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final long identityToken = Binder.clearCallingIdentity(); - final boolean success = connection.findAccessibilityNodeInfosByText( - accessibilityWindowId, accessibilityNodeId, text, interactionId, this, - Thread.currentThread().getId()); - Binder.restoreCallingIdentity(identityToken); - if (success) { + final String[] packageNames; + try { + packageNames = connection.findAccessibilityNodeInfosByText( + accessibilityWindowId, accessibilityNodeId, text, interactionId, this, + Thread.currentThread().getId()); + } finally { + Binder.restoreCallingIdentity(identityToken); + } + + if (packageNames != null) { List<AccessibilityNodeInfo> infos = getFindAccessibilityNodeInfosResultAndClear( interactionId); if (infos != null) { - finalizeAndCacheAccessibilityNodeInfos(infos, connectionId); + finalizeAndCacheAccessibilityNodeInfos(infos, connectionId, + false, packageNames); return infos; } } @@ -426,14 +447,19 @@ public final class AccessibilityInteractionClient if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final long identityToken = Binder.clearCallingIdentity(); - final boolean success = connection.findFocus(accessibilityWindowId, - accessibilityNodeId, focusType, interactionId, this, - Thread.currentThread().getId()); - Binder.restoreCallingIdentity(identityToken); - if (success) { + final String[] packageNames; + try { + packageNames = connection.findFocus(accessibilityWindowId, + accessibilityNodeId, focusType, interactionId, this, + Thread.currentThread().getId()); + } finally { + Binder.restoreCallingIdentity(identityToken); + } + + if (packageNames != null) { AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( interactionId); - finalizeAndCacheAccessibilityNodeInfo(info, connectionId); + finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames); return info; } } else { @@ -470,14 +496,19 @@ public final class AccessibilityInteractionClient if (connection != null) { final int interactionId = mInteractionIdCounter.getAndIncrement(); final long identityToken = Binder.clearCallingIdentity(); - final boolean success = connection.focusSearch(accessibilityWindowId, - accessibilityNodeId, direction, interactionId, this, - Thread.currentThread().getId()); - Binder.restoreCallingIdentity(identityToken); - if (success) { + final String[] packageNames; + try { + packageNames = connection.focusSearch(accessibilityWindowId, + accessibilityNodeId, direction, interactionId, this, + Thread.currentThread().getId()); + } finally { + Binder.restoreCallingIdentity(identityToken); + } + + if (packageNames != null) { AccessibilityNodeInfo info = getFindAccessibilityNodeInfoResultAndClear( interactionId); - finalizeAndCacheAccessibilityNodeInfo(info, connectionId); + finalizeAndCacheAccessibilityNodeInfo(info, connectionId, false, packageNames); return info; } } else { @@ -578,7 +609,7 @@ public final class AccessibilityInteractionClient int interactionId) { synchronized (mInstanceLock) { final boolean success = waitForResultTimedLocked(interactionId); - List<AccessibilityNodeInfo> result = null; + final List<AccessibilityNodeInfo> result; if (success) { result = mFindAccessibilityNodeInfosResult; } else { @@ -694,13 +725,25 @@ public final class AccessibilityInteractionClient * * @param info The info. * @param connectionId The id of the connection to the system. + * @param bypassCache Whether or not to bypass the cache. The node is added to the cache if + * this value is {@code false} + * @param packageNames The valid package names a node can come from. */ private void finalizeAndCacheAccessibilityNodeInfo(AccessibilityNodeInfo info, - int connectionId) { + int connectionId, boolean bypassCache, String[] packageNames) { if (info != null) { info.setConnectionId(connectionId); + // Empty array means any package name is Okay + if (!ArrayUtils.isEmpty(packageNames) + && !ArrayUtils.contains(packageNames, info.getPackageName().toString())) { + // If the node package not one of the valid ones, pick the top one - this + // is one of the packages running in the introspected UID. + info.setPackageName(packageNames[0]); + } info.setSealed(true); - sAccessibilityCache.add(info); + if (!bypassCache) { + sAccessibilityCache.add(info); + } } } @@ -709,14 +752,18 @@ public final class AccessibilityInteractionClient * * @param infos The {@link AccessibilityNodeInfo}s. * @param connectionId The id of the connection to the system. + * @param bypassCache Whether or not to bypass the cache. The nodes are added to the cache if + * this value is {@code false} + * @param packageNames The valid package names a node can come from. */ private void finalizeAndCacheAccessibilityNodeInfos(List<AccessibilityNodeInfo> infos, - int connectionId) { + int connectionId, boolean bypassCache, String[] packageNames) { if (infos != null) { final int infosCount = infos.size(); for (int i = 0; i < infosCount; i++) { AccessibilityNodeInfo info = infos.get(i); - finalizeAndCacheAccessibilityNodeInfo(info, connectionId); + finalizeAndCacheAccessibilityNodeInfo(info, connectionId, + bypassCache, packageNames); } } } diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java index 286f5f7c1bf9..b3683c798514 100644 --- a/core/java/android/view/accessibility/AccessibilityManager.java +++ b/core/java/android/view/accessibility/AccessibilityManager.java @@ -592,7 +592,7 @@ public final class AccessibilityManager { * @hide */ public int addAccessibilityInteractionConnection(IWindow windowToken, - IAccessibilityInteractionConnection connection) { + String packageName, IAccessibilityInteractionConnection connection) { final IAccessibilityManager service; final int userId; synchronized (mLock) { @@ -603,7 +603,8 @@ public final class AccessibilityManager { userId = mUserId; } try { - return service.addAccessibilityInteractionConnection(windowToken, connection, userId); + return service.addAccessibilityInteractionConnection(windowToken, connection, + packageName, userId); } catch (RemoteException re) { Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re); } diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl index 7f44bac8bc6f..da06a111c8a4 100644 --- a/core/java/android/view/accessibility/IAccessibilityManager.aidl +++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl @@ -46,7 +46,7 @@ interface IAccessibilityManager { void interrupt(int userId); int addAccessibilityInteractionConnection(IWindow windowToken, - in IAccessibilityInteractionConnection connection, int userId); + in IAccessibilityInteractionConnection connection, String packageName, int userId); void removeAccessibilityInteractionConnection(IWindow windowToken); diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 34ccb7b82c87..62c17b7ee8dd 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -29,6 +29,7 @@ import android.app.AlertDialog; import android.app.PendingIntent; import android.app.StatusBarManager; import android.app.UiAutomation; +import android.appwidget.AppWidgetManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -69,6 +70,7 @@ import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; import android.util.Slog; import android.util.SparseArray; +import android.util.ArraySet; import android.view.Display; import android.view.IWindow; import android.view.InputDevice; @@ -92,9 +94,11 @@ import android.view.accessibility.IAccessibilityManagerClient; import com.android.internal.R; import com.android.internal.content.PackageMonitor; import com.android.internal.os.SomeArgs; +import com.android.internal.util.ArrayUtils; import com.android.server.LocalServices; import com.android.server.statusbar.StatusBarManagerInternal; +import libcore.util.EmptyArray; import org.xmlpull.v1.XmlPullParserException; import java.io.FileDescriptor; @@ -181,6 +185,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final WindowManagerInternal mWindowManagerService; + private AppWidgetManagerInternal mAppWidgetService; + private final SecurityPolicy mSecurityPolicy; private final MainHandler mMainHandler; @@ -207,7 +213,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final RemoteCallbackList<IAccessibilityManagerClient> mGlobalClients = new RemoteCallbackList<>(); - private final SparseArray<AccessibilityConnectionWrapper> mGlobalInteractionConnections = + private final SparseArray<RemoteAccessibilityConnection> mGlobalInteractionConnections = new SparseArray<>(); private final SparseArray<IBinder> mGlobalWindowTokens = new SparseArray<>(); @@ -458,6 +464,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { // performs the current profile parent resolution.. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); + + // Make sure the reported package is one the caller has access to. + event.setPackageName(mSecurityPolicy.resolveValidReportedPackageLocked( + event.getPackageName(), UserHandle.getCallingAppId(), resolvedUserId)); + // This method does nothing for a background user. if (resolvedUserId != mCurrentUserId) { return true; // yes, recycle the event @@ -573,30 +584,38 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { @Override public int addAccessibilityInteractionConnection(IWindow windowToken, - IAccessibilityInteractionConnection connection, int userId) throws RemoteException { + IAccessibilityInteractionConnection connection, String packageName, + int userId) throws RemoteException { synchronized (mLock) { // We treat calls from a profile as if made by its parent as profiles // share the accessibility state of the parent. The call below // performs the current profile parent resolution. final int resolvedUserId = mSecurityPolicy .resolveCallingUserIdEnforcingPermissionsLocked(userId); + final int resolvedUid = UserHandle.getUid(resolvedUserId, UserHandle.getCallingAppId()); + + // Make sure the reported package is one the caller has access to. + packageName = mSecurityPolicy.resolveValidReportedPackageLocked( + packageName, UserHandle.getCallingAppId(), resolvedUserId); + final int windowId = sNextWindowId++; // If the window is from a process that runs across users such as // the system UI or the system we add it to the global state that // is shared across users. if (mSecurityPolicy.isCallerInteractingAcrossUsers(userId)) { - AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( - windowId, connection, UserHandle.USER_ALL); + RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection( + windowId, connection, packageName, resolvedUid, UserHandle.USER_ALL); wrapper.linkToDeath(); mGlobalInteractionConnections.put(windowId, wrapper); mGlobalWindowTokens.put(windowId, windowToken.asBinder()); if (DEBUG) { Slog.i(LOG_TAG, "Added global connection for pid:" + Binder.getCallingPid() - + " with windowId: " + windowId + " and token: " + windowToken.asBinder()); + + " with windowId: " + windowId + " and token: " + + windowToken.asBinder()); } } else { - AccessibilityConnectionWrapper wrapper = new AccessibilityConnectionWrapper( - windowId, connection, resolvedUserId); + RemoteAccessibilityConnection wrapper = new RemoteAccessibilityConnection( + windowId, connection, packageName, resolvedUid, resolvedUserId); wrapper.linkToDeath(); UserState userState = getUserStateLocked(resolvedUserId); userState.mInteractionConnections.put(windowId, wrapper); @@ -625,7 +644,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { if (removedWindowId >= 0) { if (DEBUG) { Slog.i(LOG_TAG, "Removed global connection for pid:" + Binder.getCallingPid() - + " with windowId: " + removedWindowId + " and token: " + window.asBinder()); + + " with windowId: " + removedWindowId + " and token: " + + window.asBinder()); } return; } @@ -649,13 +669,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private int removeAccessibilityInteractionConnectionInternalLocked(IBinder windowToken, SparseArray<IBinder> windowTokens, - SparseArray<AccessibilityConnectionWrapper> interactionConnections) { + SparseArray<RemoteAccessibilityConnection> interactionConnections) { final int count = windowTokens.size(); for (int i = 0; i < count; i++) { if (windowTokens.valueAt(i) == windowToken) { final int windowId = windowTokens.keyAt(i); windowTokens.removeAt(i); - AccessibilityConnectionWrapper wrapper = interactionConnections.get(windowId); + RemoteAccessibilityConnection wrapper = interactionConnections.get(windowId); wrapper.unlinkToDeath(); interactionConnections.remove(windowId); return windowId; @@ -1997,18 +2017,35 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } - private class AccessibilityConnectionWrapper implements DeathRecipient { + class RemoteAccessibilityConnection implements DeathRecipient { + private final int mUid; + private final String mPackageName; private final int mWindowId; private final int mUserId; private final IAccessibilityInteractionConnection mConnection; - public AccessibilityConnectionWrapper(int windowId, - IAccessibilityInteractionConnection connection, int userId) { + RemoteAccessibilityConnection(int windowId, + IAccessibilityInteractionConnection connection, + String packageName, int uid, int userId) { mWindowId = windowId; + mPackageName = packageName; + mUid = uid; mUserId = userId; mConnection = connection; } + public int getUid() { + return mUid; + } + + public String getPackageName() { + return mPackageName; + } + + public IAccessibilityInteractionConnection getRemote() { + return mConnection; + } + public void linkToDeath() throws RemoteException { mConnection.asBinder().linkToDeath(this, 0); } @@ -2545,26 +2582,26 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } @Override - public boolean findAccessibilityNodeInfosByViewId(int accessibilityWindowId, + public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId, long accessibilityNodeId, String viewIdResName, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) throws RemoteException { final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; + RemoteAccessibilityConnection connection = null; Region partialInteractiveRegion = Region.obtain(); synchronized (mLock) { if (!isCalledForCurrentUserLocked()) { - return false; + return null; } resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); if (!permissionGranted) { - return false; + return null; } else { connection = getConnectionLocked(resolvedWindowId); if (connection == null) { - return false; + return null; } } if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( @@ -2574,13 +2611,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } final int interrogatingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); final long identityToken = Binder.clearCallingIdentity(); MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); try { - connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, viewIdResName, - partialInteractiveRegion, interactionId, callback, mFetchFlags, - interrogatingPid, interrogatingTid, spec); - return true; + connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId, + viewIdResName, partialInteractiveRegion, interactionId, callback, + mFetchFlags, interrogatingPid, interrogatingTid, spec); + return mSecurityPolicy.computeValidReportedPackages(callingUid, + connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId()."); @@ -2588,34 +2627,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } finally { Binder.restoreCallingIdentity(identityToken); // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { partialInteractiveRegion.recycle(); } } - return false; + return null; } @Override - public boolean findAccessibilityNodeInfosByText(int accessibilityWindowId, + public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) throws RemoteException { final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; + RemoteAccessibilityConnection connection = null; Region partialInteractiveRegion = Region.obtain(); synchronized (mLock) { if (!isCalledForCurrentUserLocked()) { - return false; + return null; } resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); if (!permissionGranted) { - return false; + return null; } else { connection = getConnectionLocked(resolvedWindowId); if (connection == null) { - return false; + return null; } } if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( @@ -2625,13 +2664,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } final int interrogatingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); final long identityToken = Binder.clearCallingIdentity(); MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); try { - connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text, + connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId, text, partialInteractiveRegion, interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, spec); - return true; + return mSecurityPolicy.computeValidReportedPackages(callingUid, + connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()"); @@ -2639,34 +2680,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } finally { Binder.restoreCallingIdentity(identityToken); // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { partialInteractiveRegion.recycle(); } } - return false; + return null; } @Override - public boolean findAccessibilityNodeInfoByAccessibilityId( + public String[] findAccessibilityNodeInfoByAccessibilityId( int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, long interrogatingTid) throws RemoteException { final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; + RemoteAccessibilityConnection connection = null; Region partialInteractiveRegion = Region.obtain(); synchronized (mLock) { if (!isCalledForCurrentUserLocked()) { - return false; + return null; } resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); if (!permissionGranted) { - return false; + return null; } else { connection = getConnectionLocked(resolvedWindowId); if (connection == null) { - return false; + return null; } } if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( @@ -2676,13 +2717,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } final int interrogatingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); final long identityToken = Binder.clearCallingIdentity(); MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); try { - connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId, - partialInteractiveRegion, interactionId, callback, mFetchFlags | flags, - interrogatingPid, interrogatingTid, spec); - return true; + connection.getRemote().findAccessibilityNodeInfoByAccessibilityId( + accessibilityNodeId, partialInteractiveRegion, interactionId, callback, + mFetchFlags | flags, interrogatingPid, interrogatingTid, spec); + return mSecurityPolicy.computeValidReportedPackages(callingUid, + connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()"); @@ -2690,35 +2733,35 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } finally { Binder.restoreCallingIdentity(identityToken); // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { partialInteractiveRegion.recycle(); } } - return false; + return null; } @Override - public boolean findFocus(int accessibilityWindowId, long accessibilityNodeId, + public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) throws RemoteException { final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; + RemoteAccessibilityConnection connection = null; Region partialInteractiveRegion = Region.obtain(); synchronized (mLock) { if (!isCalledForCurrentUserLocked()) { - return false; + return null; } resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked( accessibilityWindowId, focusType); final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); if (!permissionGranted) { - return false; + return null; } else { connection = getConnectionLocked(resolvedWindowId); if (connection == null) { - return false; + return null; } } if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( @@ -2728,13 +2771,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } final int interrogatingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); final long identityToken = Binder.clearCallingIdentity(); MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); try { - connection.findFocus(accessibilityNodeId, focusType, partialInteractiveRegion, - interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, - spec); - return true; + connection.getRemote().findFocus(accessibilityNodeId, focusType, + partialInteractiveRegion, interactionId, callback, mFetchFlags, + interrogatingPid, interrogatingTid, spec); + return mSecurityPolicy.computeValidReportedPackages(callingUid, + connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling findFocus()"); @@ -2742,34 +2787,34 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } finally { Binder.restoreCallingIdentity(identityToken); // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { partialInteractiveRegion.recycle(); } } - return false; + return null; } @Override - public boolean focusSearch(int accessibilityWindowId, long accessibilityNodeId, + public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) throws RemoteException { final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; + RemoteAccessibilityConnection connection = null; Region partialInteractiveRegion = Region.obtain(); synchronized (mLock) { if (!isCalledForCurrentUserLocked()) { - return false; + return null; } resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId); final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId); if (!permissionGranted) { - return false; + return null; } else { connection = getConnectionLocked(resolvedWindowId); if (connection == null) { - return false; + return null; } } if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked( @@ -2779,13 +2824,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } final int interrogatingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); final long identityToken = Binder.clearCallingIdentity(); MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId); try { - connection.focusSearch(accessibilityNodeId, direction, partialInteractiveRegion, - interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid, - spec); - return true; + connection.getRemote().focusSearch(accessibilityNodeId, direction, + partialInteractiveRegion, interactionId, callback, mFetchFlags, + interrogatingPid, interrogatingTid, spec); + return mSecurityPolicy.computeValidReportedPackages(callingUid, + connection.getPackageName(), connection.getUid()); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()"); @@ -2793,11 +2840,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } finally { Binder.restoreCallingIdentity(identityToken); // Recycle if passed to another process. - if (partialInteractiveRegion != null && Binder.isProxy(connection)) { + if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) { partialInteractiveRegion.recycle(); } } - return false; + return null; } @Override @@ -2844,7 +2891,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) throws RemoteException { final int resolvedWindowId; - IAccessibilityInteractionConnection connection = null; + RemoteAccessibilityConnection connection; synchronized (mLock) { if (!isCalledForCurrentUserLocked()) { return false; @@ -2869,8 +2916,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mPowerManager.userActivity(SystemClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0); - connection.performAccessibilityAction(accessibilityNodeId, action, arguments, - interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid); + connection.mConnection.performAccessibilityAction(accessibilityNodeId, action, + arguments, interactionId, callback, mFetchFlags, interrogatingPid, + interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error calling performAccessibilityAction()"); @@ -3417,16 +3465,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen(); } - private IAccessibilityInteractionConnection getConnectionLocked(int windowId) { + private RemoteAccessibilityConnection getConnectionLocked(int windowId) { if (DEBUG) { Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId); } - AccessibilityConnectionWrapper wrapper = mGlobalInteractionConnections.get(windowId); + RemoteAccessibilityConnection wrapper = mGlobalInteractionConnections.get(windowId); if (wrapper == null) { wrapper = getCurrentUserStateLocked().mInteractionConnections.get(windowId); } if (wrapper != null && wrapper.mConnection != null) { - return wrapper.mConnection; + return wrapper; } if (DEBUG) { Slog.e(LOG_TAG, "No interaction connection to window: " + windowId); @@ -3538,6 +3586,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + private AppWidgetManagerInternal getAppWidgetManager() { + synchronized (mLock) { + if (mAppWidgetService == null + && mPackageManager.hasSystemFeature(PackageManager.FEATURE_APP_WIDGETS)) { + mAppWidgetService = LocalServices.getService(AppWidgetManagerInternal.class); + } + return mAppWidgetService; + } + } + final class WindowsForAccessibilityCallback implements WindowManagerInternal.WindowsForAccessibilityCallback { @@ -3804,6 +3862,78 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } + private boolean isValidPackageForUid(String packageName, int uid) { + try { + return uid == mPackageManager.getPackageUid( + packageName, UserHandle.getUserId(uid)); + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + + String resolveValidReportedPackageLocked(CharSequence packageName, int appId, int userId) { + // Okay to pass no package + if (packageName == null) { + return null; + } + // The system gets to pass any package + if (appId == Process.SYSTEM_UID) { + return packageName.toString(); + } + // Passing a package in your UID is fine + final String packageNameStr = packageName.toString(); + final int resolvedUid = UserHandle.getUid(userId, appId); + if (isValidPackageForUid(packageNameStr, resolvedUid)) { + return packageName.toString(); + } + // Appwidget hosts get to pass packages for widgets they host + final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager(); + if (appWidgetManager != null && ArrayUtils.contains(appWidgetManager + .getHostedWidgetPackages(resolvedUid), packageNameStr)) { + return packageName.toString(); + } + // Otherwise, set the package to the first one in the UID + final String[] packageNames = mPackageManager.getPackagesForUid(resolvedUid); + if (ArrayUtils.isEmpty(packageNames)) { + return null; + } + // Okay, the caller reported a package it does not have access to. + // Instead of crashing the caller for better backwards compatibility + // we report the first package in the UID. Since most of the time apps + // don't use shared user id, this will yield correct results and for + // the edge case of using a shared user id we may report the wrong + // package but this is fine since first, this is a cheating app and + // second there is no way to get the correct package anyway. + return packageNames[0]; + } + + String[] computeValidReportedPackages(int callingUid, + String targetPackage, int targetUid) { + if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) { + // Empty array means any package is Okay + return EmptyArray.STRING; + } + // IMPORTANT: The target package is already vetted to be in the target UID + String[] uidPackages = new String[]{targetPackage}; + // Appwidget hosts get to pass packages for widgets they host + final AppWidgetManagerInternal appWidgetManager = getAppWidgetManager(); + if (appWidgetManager != null) { + final ArraySet<String> widgetPackages = appWidgetManager + .getHostedWidgetPackages(targetUid); + if (widgetPackages != null && !widgetPackages.isEmpty()) { + final String[] validPackages = new String[uidPackages.length + + widgetPackages.size()]; + System.arraycopy(uidPackages, 0, validPackages, 0, uidPackages.length); + final int widgetPackageCount = widgetPackages.size(); + for (int i = 0; i < widgetPackageCount; i++) { + validPackages[uidPackages.length + i] = widgetPackages.valueAt(i); + } + return validPackages; + } + } + return uidPackages; + } + public void clearWindowsLocked() { List<AccessibilityWindowInfo> windows = Collections.emptyList(); final int activeWindowId = mActiveWindowId; @@ -4202,7 +4332,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { public final RemoteCallbackList<IAccessibilityManagerClient> mClients = new RemoteCallbackList<>(); - public final SparseArray<AccessibilityConnectionWrapper> mInteractionConnections = + public final SparseArray<RemoteAccessibilityConnection> mInteractionConnections = new SparseArray<>(); public final SparseArray<IBinder> mWindowTokens = new SparseArray<>(); diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java index b5fcb5cb6a3b..eed0a26af722 100644 --- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java +++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java @@ -29,6 +29,7 @@ import android.app.PendingIntent; import android.app.admin.DevicePolicyManagerInternal; import android.app.admin.DevicePolicyManagerInternal.OnCrossProfileWidgetProvidersChangeListener; import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetManagerInternal; import android.appwidget.AppWidgetProviderInfo; import android.appwidget.PendingHostUpdate; import android.content.BroadcastReceiver; @@ -92,6 +93,7 @@ import com.android.internal.appwidget.IAppWidgetHost; import com.android.internal.appwidget.IAppWidgetService; import com.android.internal.os.BackgroundThread; import com.android.internal.os.SomeArgs; +import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.widget.IRemoteViewsAdapterConnection; import com.android.internal.widget.IRemoteViewsFactory; @@ -100,6 +102,7 @@ import com.android.server.WidgetBackupProvider; import com.android.server.policy.IconUtilities; import libcore.io.IoUtils; +import libcore.util.EmptyArray; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -243,6 +246,8 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku computeMaximumWidgetBitmapMemory(); registerBroadcastReceiver(); registerOnCrossProfileProvidersChangedListener(); + + LocalServices.addService(AppWidgetManagerInternal.class, new AppWidgetManagerLocal()); } private void computeMaximumWidgetBitmapMemory() { @@ -4604,4 +4609,24 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku } } } + + private class AppWidgetManagerLocal extends AppWidgetManagerInternal { + @Override + public ArraySet<String> getHostedWidgetPackages(int uid) { + synchronized (mLock) { + ArraySet<String> widgetPackages = null; + final int widgetCount = mWidgets.size(); + for (int i = 0; i < widgetCount; i++) { + final Widget widget = mWidgets.get(i); + if (widget.host.id.uid == uid) { + if (widgetPackages == null) { + widgetPackages = new ArraySet<>(); + } + widgetPackages.add(widget.provider.id.componentName.getPackageName()); + } + } + return widgetPackages; + } + } + } } |