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

Commit 7ef7accd authored by Pinyao Ting's avatar Pinyao Ting Committed by Android Build Coastguard Worker
Browse files

Enforce hard limits on hosts per package and widgets per host.

Bug: 353240784
Test: manually verified with PoC app that at most 20 hosts can exists
Flag: EXEMPT CVE
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:996da163274b338e57228eda79dac2d9cae537b8)
Merged-In: I60ee7faf57ed719f93cafad212fef24964dec99f
Change-Id: I60ee7faf57ed719f93cafad212fef24964dec99f
parent 226a778c
Loading
Loading
Loading
Loading
+49 −1
Original line number Diff line number Diff line
@@ -170,6 +170,15 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
    // used to verify which request has successfully been received by the host.
    private static final AtomicLong UPDATE_COUNTER = new AtomicLong();

    // Hard limit of number of hosts an app can create, note that the app that hosts the widgets
    // can have multiple instances of {@link AppWidgetHost}, typically in respect to different
    // surfaces in the host app.
    // @see AppWidgetHost
    // @see AppWidgetHost#mHostId
    private static final int MAX_NUMBER_OF_HOSTS_PER_PACKAGE = 20;
    // Hard limit of number of widgets can be pinned by a host.
    private static final int MAX_NUMBER_OF_WIDGETS_PER_HOST = 200;

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -1698,7 +1707,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        if (host != null) {
            return host;
        }

        ensureHostCountBeforeAddLocked(id);
        host = new Host();
        host.id = id;
        mHosts.add(host);
@@ -1706,6 +1715,24 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
        return host;
    }

    /**
     * Ensures that the number of hosts for a package is less than the maximum number of hosts per
     * package. If the number of hosts is greater than the maximum number of hosts per package, then
     * removes the oldest host.
     */
    private void ensureHostCountBeforeAddLocked(HostId hostId) {
        final List<Host> hosts = new ArrayList<>();
        for (Host host : mHosts) {
            if (host.id.uid == hostId.uid
                    && host.id.packageName.equals(hostId.packageName)) {
                hosts.add(host);
            }
        }
        while (hosts.size() >= MAX_NUMBER_OF_HOSTS_PER_PACKAGE) {
            deleteHostLocked(hosts.remove(0));
        }
    }

    private void deleteHostLocked(Host host) {
        final int N = host.widgets.size();
        for (int i = N - 1; i >= 0; i--) {
@@ -2843,11 +2870,32 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
     * Adds the widget to mWidgets and tracks the package name in mWidgetPackages.
     */
    void addWidgetLocked(Widget widget) {
        ensureWidgetCountBeforeAddLocked(widget);
        mWidgets.add(widget);

        onWidgetProviderAddedOrChangedLocked(widget);
    }

    /**
     * Ensures that the widget count for the widget's host is not greater than the maximum
     * number of widgets per host. If the count is greater than the maximum, removes oldest widgets
     * from the host until the count is less than or equal to the maximum.
     */
    private void ensureWidgetCountBeforeAddLocked(Widget widget) {
        if (widget.host == null || widget.host.id == null) {
            return;
        }
        final List<Widget> widgetsInSameHost = new ArrayList<>();
        for (Widget w : mWidgets) {
            if (w.host != null && widget.host.id.equals(w.host.id)) {
                widgetsInSameHost.add(w);
            }
        }
        while (widgetsInSameHost.size() >= MAX_NUMBER_OF_WIDGETS_PER_HOST) {
            removeWidgetLocked(widgetsInSameHost.remove(0));
        }
    }

    /**
     * Checks if the provider is assigned and updates the mWidgetPackages to track packages
     * that have bound widgets.