]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 6 Jan 2021 18:08:53 +0000 (19:08 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 6 Jan 2021 18:08:53 +0000 (19:08 +0100)
added patches:
xen-xenbus-add-will_handle-callback-support-in-xenbus_watch_path.patch
xen-xenbus-allow-watches-discard-events-before-queueing.patch
xen-xenbus-count-pending-messages-for-each-watch.patch
xen-xenbus-xen_bus_type-support-will_handle-watch-callback.patch
xenbus-xenbus_backend-disallow-pending-watch-messages.patch

queue-4.9/series
queue-4.9/xen-xenbus-add-will_handle-callback-support-in-xenbus_watch_path.patch [new file with mode: 0644]
queue-4.9/xen-xenbus-allow-watches-discard-events-before-queueing.patch [new file with mode: 0644]
queue-4.9/xen-xenbus-count-pending-messages-for-each-watch.patch [new file with mode: 0644]
queue-4.9/xen-xenbus-xen_bus_type-support-will_handle-watch-callback.patch [new file with mode: 0644]
queue-4.9/xenbus-xenbus_backend-disallow-pending-watch-messages.patch [new file with mode: 0644]

index 92c63e07cab1ff3a15c106587fce7ca7394d913d..929423c55d25f2f96954259ca1d41162b3ad7594 100644 (file)
@@ -23,3 +23,8 @@ quota-don-t-overflow-quota-file-offsets.patch
 powerpc-sysdev-add-missing-iounmap-on-error-in-mpic_.patch
 module-delay-kobject-uevent-until-after-module-init-.patch
 kdev_t-always-inline-major-minor-helper-functions.patch
+xen-xenbus-allow-watches-discard-events-before-queueing.patch
+xen-xenbus-add-will_handle-callback-support-in-xenbus_watch_path.patch
+xen-xenbus-xen_bus_type-support-will_handle-watch-callback.patch
+xen-xenbus-count-pending-messages-for-each-watch.patch
+xenbus-xenbus_backend-disallow-pending-watch-messages.patch
diff --git a/queue-4.9/xen-xenbus-add-will_handle-callback-support-in-xenbus_watch_path.patch b/queue-4.9/xen-xenbus-add-will_handle-callback-support-in-xenbus_watch_path.patch
new file mode 100644 (file)
index 0000000..85b34fb
--- /dev/null
@@ -0,0 +1,141 @@
+From 2e85d32b1c865bec703ce0c962221a5e955c52c2 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sjpark@amazon.de>
+Date: Mon, 14 Dec 2020 10:04:18 +0100
+Subject: xen/xenbus: Add 'will_handle' callback support in xenbus_watch_path()
+
+From: SeongJae Park <sjpark@amazon.de>
+
+commit 2e85d32b1c865bec703ce0c962221a5e955c52c2 upstream.
+
+Some code does not directly make 'xenbus_watch' object and call
+'register_xenbus_watch()' but use 'xenbus_watch_path()' instead.  This
+commit adds support of 'will_handle' callback in the
+'xenbus_watch_path()' and it's wrapper, 'xenbus_watch_pathfmt()'.
+
+This is part of XSA-349
+
+Cc: stable@vger.kernel.org
+Signed-off-by: SeongJae Park <sjpark@amazon.de>
+Reported-by: Michael Kurth <mku@amazon.de>
+Reported-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/block/xen-blkback/xenbus.c |    3 ++-
+ drivers/net/xen-netback/xenbus.c   |    2 +-
+ drivers/xen/xen-pciback/xenbus.c   |    2 +-
+ drivers/xen/xenbus/xenbus_client.c |    9 +++++++--
+ drivers/xen/xenbus/xenbus_probe.c  |    2 +-
+ include/xen/xenbus.h               |    6 +++++-
+ 6 files changed, 17 insertions(+), 7 deletions(-)
+
+--- a/drivers/block/xen-blkback/xenbus.c
++++ b/drivers/block/xen-blkback/xenbus.c
+@@ -646,7 +646,8 @@ static int xen_blkbk_probe(struct xenbus
+       /* setup back pointer */
+       be->blkif->be = be;
+-      err = xenbus_watch_pathfmt(dev, &be->backend_watch, backend_changed,
++      err = xenbus_watch_pathfmt(dev, &be->backend_watch, NULL,
++                                 backend_changed,
+                                  "%s/%s", dev->nodename, "physical-device");
+       if (err)
+               goto fail;
+--- a/drivers/net/xen-netback/xenbus.c
++++ b/drivers/net/xen-netback/xenbus.c
+@@ -1040,7 +1040,7 @@ static void connect(struct backend_info
+       xenvif_carrier_on(be->vif);
+       unregister_hotplug_status_watch(be);
+-      err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
++      err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, NULL,
+                                  hotplug_status_changed,
+                                  "%s/%s", dev->nodename, "hotplug-status");
+       if (!err)
+--- a/drivers/xen/xen-pciback/xenbus.c
++++ b/drivers/xen/xen-pciback/xenbus.c
+@@ -689,7 +689,7 @@ static int xen_pcibk_xenbus_probe(struct
+       /* watch the backend node for backend configuration information */
+       err = xenbus_watch_path(dev, dev->nodename, &pdev->be_watch,
+-                              xen_pcibk_be_watch);
++                              NULL, xen_pcibk_be_watch);
+       if (err)
+               goto out;
+--- a/drivers/xen/xenbus/xenbus_client.c
++++ b/drivers/xen/xenbus/xenbus_client.c
+@@ -114,19 +114,22 @@ EXPORT_SYMBOL_GPL(xenbus_strstate);
+  */
+ int xenbus_watch_path(struct xenbus_device *dev, const char *path,
+                     struct xenbus_watch *watch,
++                    bool (*will_handle)(struct xenbus_watch *,
++                                        const char **, unsigned int),
+                     void (*callback)(struct xenbus_watch *,
+                                      const char **, unsigned int))
+ {
+       int err;
+       watch->node = path;
+-      watch->will_handle = NULL;
++      watch->will_handle = will_handle;
+       watch->callback = callback;
+       err = register_xenbus_watch(watch);
+       if (err) {
+               watch->node = NULL;
++              watch->will_handle = NULL;
+               watch->callback = NULL;
+               xenbus_dev_fatal(dev, err, "adding watch on %s", path);
+       }
+@@ -153,6 +156,8 @@ EXPORT_SYMBOL_GPL(xenbus_watch_path);
+  */
+ int xenbus_watch_pathfmt(struct xenbus_device *dev,
+                        struct xenbus_watch *watch,
++                       bool (*will_handle)(struct xenbus_watch *,
++                                           const char **, unsigned int),
+                        void (*callback)(struct xenbus_watch *,
+                                       const char **, unsigned int),
+                        const char *pathfmt, ...)
+@@ -169,7 +174,7 @@ int xenbus_watch_pathfmt(struct xenbus_d
+               xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
+               return -ENOMEM;
+       }
+-      err = xenbus_watch_path(dev, path, watch, callback);
++      err = xenbus_watch_path(dev, path, watch, will_handle, callback);
+       if (err)
+               kfree(path);
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -137,7 +137,7 @@ static int watch_otherend(struct xenbus_
+               container_of(dev->dev.bus, struct xen_bus_type, bus);
+       return xenbus_watch_pathfmt(dev, &dev->otherend_watch,
+-                                  bus->otherend_changed,
++                                  NULL, bus->otherend_changed,
+                                   "%s/%s", dev->otherend, "state");
+ }
+--- a/include/xen/xenbus.h
++++ b/include/xen/xenbus.h
+@@ -201,10 +201,14 @@ void xenbus_suspend_cancel(void);
+ int xenbus_watch_path(struct xenbus_device *dev, const char *path,
+                     struct xenbus_watch *watch,
++                    bool (*will_handle)(struct xenbus_watch *,
++                                        const char **, unsigned int),
+                     void (*callback)(struct xenbus_watch *,
+                                      const char **, unsigned int));
+-__printf(4, 5)
++__printf(5, 6)
+ int xenbus_watch_pathfmt(struct xenbus_device *dev, struct xenbus_watch *watch,
++                       bool (*will_handle)(struct xenbus_watch *,
++                                           const char **, unsigned int),
+                        void (*callback)(struct xenbus_watch *,
+                                         const char **, unsigned int),
+                        const char *pathfmt, ...);
diff --git a/queue-4.9/xen-xenbus-allow-watches-discard-events-before-queueing.patch b/queue-4.9/xen-xenbus-allow-watches-discard-events-before-queueing.patch
new file mode 100644 (file)
index 0000000..9af8948
--- /dev/null
@@ -0,0 +1,102 @@
+From fed1755b118147721f2c87b37b9d66e62c39b668 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sjpark@amazon.de>
+Date: Mon, 14 Dec 2020 10:02:45 +0100
+Subject: xen/xenbus: Allow watches discard events before queueing
+
+From: SeongJae Park <sjpark@amazon.de>
+
+commit fed1755b118147721f2c87b37b9d66e62c39b668 upstream.
+
+If handling logics of watch events are slower than the events enqueue
+logic and the events can be created from the guests, the guests could
+trigger memory pressure by intensively inducing the events, because it
+will create a huge number of pending events that exhausting the memory.
+
+Fortunately, some watch events could be ignored, depending on its
+handler callback.  For example, if the callback has interest in only one
+single path, the watch wouldn't want multiple pending events.  Or, some
+watches could ignore events to same path.
+
+To let such watches to volutarily help avoiding the memory pressure
+situation, this commit introduces new watch callback, 'will_handle'.  If
+it is not NULL, it will be called for each new event just before
+enqueuing it.  Then, if the callback returns false, the event will be
+discarded.  No watch is using the callback for now, though.
+
+This is part of XSA-349
+
+Cc: stable@vger.kernel.org
+Signed-off-by: SeongJae Park <sjpark@amazon.de>
+Reported-by: Michael Kurth <mku@amazon.de>
+Reported-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/net/xen-netback/xenbus.c   |    2 ++
+ drivers/xen/xenbus/xenbus_client.c |    1 +
+ drivers/xen/xenbus/xenbus_xs.c     |    7 ++++++-
+ include/xen/xenbus.h               |    7 +++++++
+ 4 files changed, 16 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/xen-netback/xenbus.c
++++ b/drivers/net/xen-netback/xenbus.c
+@@ -770,12 +770,14 @@ static int xen_register_credit_watch(str
+               return -ENOMEM;
+       snprintf(node, maxlen, "%s/rate", dev->nodename);
+       vif->credit_watch.node = node;
++      vif->credit_watch.will_handle = NULL;
+       vif->credit_watch.callback = xen_net_rate_changed;
+       err = register_xenbus_watch(&vif->credit_watch);
+       if (err) {
+               pr_err("Failed to set watcher %s\n", vif->credit_watch.node);
+               kfree(node);
+               vif->credit_watch.node = NULL;
++              vif->credit_watch.will_handle = NULL;
+               vif->credit_watch.callback = NULL;
+       }
+       return err;
+--- a/drivers/xen/xenbus/xenbus_client.c
++++ b/drivers/xen/xenbus/xenbus_client.c
+@@ -120,6 +120,7 @@ int xenbus_watch_path(struct xenbus_devi
+       int err;
+       watch->node = path;
++      watch->will_handle = NULL;
+       watch->callback = callback;
+       err = register_xenbus_watch(watch);
+--- a/drivers/xen/xenbus/xenbus_xs.c
++++ b/drivers/xen/xenbus/xenbus_xs.c
+@@ -901,7 +901,12 @@ static int process_msg(void)
+               spin_lock(&watches_lock);
+               msg->u.watch.handle = find_watch(
+                       msg->u.watch.vec[XS_WATCH_TOKEN]);
+-              if (msg->u.watch.handle != NULL) {
++              if (msg->u.watch.handle != NULL &&
++                              (!msg->u.watch.handle->will_handle ||
++                               msg->u.watch.handle->will_handle(
++                                       msg->u.watch.handle,
++                                       (const char **)msg->u.watch.vec,
++                                       msg->u.watch.vec_size))) {
+                       spin_lock(&watch_events_lock);
+                       list_add_tail(&msg->list, &watch_events);
+                       wake_up(&watch_events_waitq);
+--- a/include/xen/xenbus.h
++++ b/include/xen/xenbus.h
+@@ -58,6 +58,13 @@ struct xenbus_watch
+       /* Path being watched. */
+       const char *node;
++      /*
++       * Called just before enqueing new event while a spinlock is held.
++       * The event will be discarded if this callback returns false.
++       */
++      bool (*will_handle)(struct xenbus_watch *,
++                          const char **vec, unsigned int len);
++
+       /* Callback (executed in a process context with no locks held). */
+       void (*callback)(struct xenbus_watch *,
+                        const char **vec, unsigned int len);
diff --git a/queue-4.9/xen-xenbus-count-pending-messages-for-each-watch.patch b/queue-4.9/xen-xenbus-count-pending-messages-for-each-watch.patch
new file mode 100644 (file)
index 0000000..ee732b6
--- /dev/null
@@ -0,0 +1,111 @@
+From 3dc86ca6b4c8cfcba9da7996189d1b5a358a94fc Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sjpark@amazon.de>
+Date: Mon, 14 Dec 2020 10:07:13 +0100
+Subject: xen/xenbus: Count pending messages for each watch
+
+From: SeongJae Park <sjpark@amazon.de>
+
+commit 3dc86ca6b4c8cfcba9da7996189d1b5a358a94fc upstream.
+
+This commit adds a counter of pending messages for each watch in the
+struct.  It is used to skip unnecessary pending messages lookup in
+'unregister_xenbus_watch()'.  It could also be used in 'will_handle'
+callback.
+
+This is part of XSA-349
+
+Cc: stable@vger.kernel.org
+Signed-off-by: SeongJae Park <sjpark@amazon.de>
+Reported-by: Michael Kurth <mku@amazon.de>
+Reported-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/xen/xenbus/xenbus_xs.c |   31 +++++++++++++++++++------------
+ include/xen/xenbus.h           |    2 ++
+ 2 files changed, 21 insertions(+), 12 deletions(-)
+
+--- a/drivers/xen/xenbus/xenbus_xs.c
++++ b/drivers/xen/xenbus/xenbus_xs.c
+@@ -699,6 +699,8 @@ int register_xenbus_watch(struct xenbus_
+       sprintf(token, "%lX", (long)watch);
++      watch->nr_pending = 0;
++
+       down_read(&xs_state.watch_mutex);
+       spin_lock(&watches_lock);
+@@ -748,12 +750,15 @@ void unregister_xenbus_watch(struct xenb
+       /* Cancel pending watch events. */
+       spin_lock(&watch_events_lock);
+-      list_for_each_entry_safe(msg, tmp, &watch_events, list) {
+-              if (msg->u.watch.handle != watch)
+-                      continue;
+-              list_del(&msg->list);
+-              kfree(msg->u.watch.vec);
+-              kfree(msg);
++      if (watch->nr_pending) {
++              list_for_each_entry_safe(msg, tmp, &watch_events, list) {
++                      if (msg->u.watch.handle != watch)
++                              continue;
++                      list_del(&msg->list);
++                      kfree(msg->u.watch.vec);
++                      kfree(msg);
++              }
++              watch->nr_pending = 0;
+       }
+       spin_unlock(&watch_events_lock);
+@@ -800,7 +805,6 @@ void xs_suspend_cancel(void)
+ static int xenwatch_thread(void *unused)
+ {
+-      struct list_head *ent;
+       struct xs_stored_msg *msg;
+       for (;;) {
+@@ -813,13 +817,15 @@ static int xenwatch_thread(void *unused)
+               mutex_lock(&xenwatch_mutex);
+               spin_lock(&watch_events_lock);
+-              ent = watch_events.next;
+-              if (ent != &watch_events)
+-                      list_del(ent);
++              msg = list_first_entry_or_null(&watch_events,
++                              struct xs_stored_msg, list);
++              if (msg) {
++                      list_del(&msg->list);
++                      msg->u.watch.handle->nr_pending--;
++              }
+               spin_unlock(&watch_events_lock);
+-              if (ent != &watch_events) {
+-                      msg = list_entry(ent, struct xs_stored_msg, list);
++              if (msg) {
+                       msg->u.watch.handle->callback(
+                               msg->u.watch.handle,
+                               (const char **)msg->u.watch.vec,
+@@ -909,6 +915,7 @@ static int process_msg(void)
+                                        msg->u.watch.vec_size))) {
+                       spin_lock(&watch_events_lock);
+                       list_add_tail(&msg->list, &watch_events);
++                      msg->u.watch.handle->nr_pending++;
+                       wake_up(&watch_events_waitq);
+                       spin_unlock(&watch_events_lock);
+               } else {
+--- a/include/xen/xenbus.h
++++ b/include/xen/xenbus.h
+@@ -58,6 +58,8 @@ struct xenbus_watch
+       /* Path being watched. */
+       const char *node;
++      unsigned int nr_pending;
++
+       /*
+        * Called just before enqueing new event while a spinlock is held.
+        * The event will be discarded if this callback returns false.
diff --git a/queue-4.9/xen-xenbus-xen_bus_type-support-will_handle-watch-callback.patch b/queue-4.9/xen-xenbus-xen_bus_type-support-will_handle-watch-callback.patch
new file mode 100644 (file)
index 0000000..7f611e1
--- /dev/null
@@ -0,0 +1,50 @@
+From be987200fbaceaef340872841d4f7af2c5ee8dc3 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sjpark@amazon.de>
+Date: Mon, 14 Dec 2020 10:05:47 +0100
+Subject: xen/xenbus/xen_bus_type: Support will_handle watch callback
+
+From: SeongJae Park <sjpark@amazon.de>
+
+commit be987200fbaceaef340872841d4f7af2c5ee8dc3 upstream.
+
+This commit adds support of the 'will_handle' watch callback for
+'xen_bus_type' users.
+
+This is part of XSA-349
+
+Cc: stable@vger.kernel.org
+Signed-off-by: SeongJae Park <sjpark@amazon.de>
+Reported-by: Michael Kurth <mku@amazon.de>
+Reported-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/xen/xenbus/xenbus_probe.c |    3 ++-
+ drivers/xen/xenbus/xenbus_probe.h |    2 ++
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/xen/xenbus/xenbus_probe.c
++++ b/drivers/xen/xenbus/xenbus_probe.c
+@@ -137,7 +137,8 @@ static int watch_otherend(struct xenbus_
+               container_of(dev->dev.bus, struct xen_bus_type, bus);
+       return xenbus_watch_pathfmt(dev, &dev->otherend_watch,
+-                                  NULL, bus->otherend_changed,
++                                  bus->otherend_will_handle,
++                                  bus->otherend_changed,
+                                   "%s/%s", dev->otherend, "state");
+ }
+--- a/drivers/xen/xenbus/xenbus_probe.h
++++ b/drivers/xen/xenbus/xenbus_probe.h
+@@ -42,6 +42,8 @@ struct xen_bus_type {
+       int (*get_bus_id)(char bus_id[XEN_BUS_ID_SIZE], const char *nodename);
+       int (*probe)(struct xen_bus_type *bus, const char *type,
+                    const char *dir);
++      bool (*otherend_will_handle)(struct xenbus_watch *watch,
++                                   const char **vec, unsigned int len);
+       void (*otherend_changed)(struct xenbus_watch *watch, const char **vec,
+                                unsigned int len);
+       struct bus_type bus;
diff --git a/queue-4.9/xenbus-xenbus_backend-disallow-pending-watch-messages.patch b/queue-4.9/xenbus-xenbus_backend-disallow-pending-watch-messages.patch
new file mode 100644 (file)
index 0000000..b8991a3
--- /dev/null
@@ -0,0 +1,57 @@
+From 9996bd494794a2fe393e97e7a982388c6249aa76 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sjpark@amazon.de>
+Date: Mon, 14 Dec 2020 10:08:40 +0100
+Subject: xenbus/xenbus_backend: Disallow pending watch messages
+
+From: SeongJae Park <sjpark@amazon.de>
+
+commit 9996bd494794a2fe393e97e7a982388c6249aa76 upstream.
+
+'xenbus_backend' watches 'state' of devices, which is writable by
+guests.  Hence, if guests intensively updates it, dom0 will have lots of
+pending events that exhausting memory of dom0.  In other words, guests
+can trigger dom0 memory pressure.  This is known as XSA-349.  However,
+the watch callback of it, 'frontend_changed()', reads only 'state', so
+doesn't need to have the pending events.
+
+To avoid the problem, this commit disallows pending watch messages for
+'xenbus_backend' using the 'will_handle()' watch callback.
+
+This is part of XSA-349
+
+Cc: stable@vger.kernel.org
+Signed-off-by: SeongJae Park <sjpark@amazon.de>
+Reported-by: Michael Kurth <mku@amazon.de>
+Reported-by: Pawel Wieczorkiewicz <wipawel@amazon.de>
+Reviewed-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+
+---
+ drivers/xen/xenbus/xenbus_probe_backend.c |    7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/drivers/xen/xenbus/xenbus_probe_backend.c
++++ b/drivers/xen/xenbus/xenbus_probe_backend.c
+@@ -181,6 +181,12 @@ static int xenbus_probe_backend(struct x
+       return err;
+ }
++static bool frontend_will_handle(struct xenbus_watch *watch,
++                               const char **vec, unsigned int len)
++{
++      return watch->nr_pending == 0;
++}
++
+ static void frontend_changed(struct xenbus_watch *watch,
+                           const char **vec, unsigned int len)
+ {
+@@ -192,6 +198,7 @@ static struct xen_bus_type xenbus_backen
+       .levels = 3,            /* backend/type/<frontend>/<id> */
+       .get_bus_id = backend_bus_id,
+       .probe = xenbus_probe_backend,
++      .otherend_will_handle = frontend_will_handle,
+       .otherend_changed = frontend_changed,
+       .bus = {
+               .name           = "xen-backend",