summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Pinyao Ting <pinyaoting@google.com> 2024-08-20 21:17:13 +0000
committer Pinyao Ting <pinyaoting@google.com> 2024-08-23 22:09:56 +0000
commit2a75f7166b028150ea0dcd142e1ede51f7861eb3 (patch)
treeb9bd32d058ce95a9b81f1a66e11b117ecaa2ba94
parent37262db58d267dc61b08f307a5605647670f47fe (diff)
Enforce hard limits on hosts per package and widgets per host.
Bug: 353240784 Change-Id: I60ee7faf57ed719f93cafad212fef24964dec99f Test: manually verified with PoC app that at most 20 hosts can exists Flag: EXEMPT CVE
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java50
1 files changed, 49 insertions, 1 deletions
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 569615e1683c..f9b731db75b1 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -217,6 +217,15 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// See {@link Provider#pendingDeletedWidgetIds}.
private static final String PENDING_DELETED_IDS_ATTR = "pending_deleted_ids";
+ // 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;
+
// Handles user and package related broadcasts.
// See {@link #registerBroadcastReceiver}
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -2275,7 +2284,7 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (host != null) {
return host;
}
-
+ ensureHostCountBeforeAddLocked(id);
host = new Host();
host.id = id;
mHosts.add(host);
@@ -2283,6 +2292,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(@NonNull final 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) {
if (DEBUG) {
Slog.i(TAG, "deleteHostLocked() " + host);
@@ -3573,12 +3600,33 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
if (DEBUG) {
Slog.i(TAG, "addWidgetLocked() " + 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(@NonNull final 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.
*/