]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 4.14
authorSasha Levin <sashal@kernel.org>
Sun, 15 Jan 2023 23:59:01 +0000 (18:59 -0500)
committerSasha Levin <sashal@kernel.org>
Sun, 15 Jan 2023 23:59:01 +0000 (18:59 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.14/hvc-xen-lock-console-list-traversal.patch [new file with mode: 0644]
queue-4.14/nfc-pn533-wait-for-out_urb-s-completion-in-pn533_usb.patch [new file with mode: 0644]
queue-4.14/regulator-da9211-use-irq-handler-when-ready.patch [new file with mode: 0644]
queue-4.14/series

diff --git a/queue-4.14/hvc-xen-lock-console-list-traversal.patch b/queue-4.14/hvc-xen-lock-console-list-traversal.patch
new file mode 100644 (file)
index 0000000..fbd0795
--- /dev/null
@@ -0,0 +1,186 @@
+From e072b2b4a99a33c7086fb7a21e01d26a2a402a82 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 30 Nov 2022 17:36:02 +0100
+Subject: hvc/xen: lock console list traversal
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Roger Pau Monne <roger.pau@citrix.com>
+
+[ Upstream commit c0dccad87cf68fc6012aec7567e354353097ec1a ]
+
+The currently lockless access to the xen console list in
+vtermno_to_xencons() is incorrect, as additions and removals from the
+list can happen anytime, and as such the traversal of the list to get
+the private console data for a given termno needs to happen with the
+lock held.  Note users that modify the list already do so with the
+lock taken.
+
+Adjust current lock takers to use the _irq{save,restore} helpers,
+since the context in which vtermno_to_xencons() is called can have
+interrupts disabled.  Use the _irq{save,restore} set of helpers to
+switch the current callers to disable interrupts in the locked region.
+I haven't checked if existing users could instead use the _irq
+variant, as I think it's safer to use _irq{save,restore} upfront.
+
+While there switch from using list_for_each_entry_safe to
+list_for_each_entry: the current entry cursor won't be removed as
+part of the code in the loop body, so using the _safe variant is
+pointless.
+
+Fixes: 02e19f9c7cac ('hvc_xen: implement multiconsole support')
+Signed-off-by: Roger Pau MonnĂ© <roger.pau@citrix.com>
+Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
+Link: https://lore.kernel.org/r/20221130163611.14686-1-roger.pau@citrix.com
+Signed-off-by: Juergen Gross <jgross@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/hvc/hvc_xen.c | 46 ++++++++++++++++++++++++---------------
+ 1 file changed, 29 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
+index 2af089b2a343..625b5660b05f 100644
+--- a/drivers/tty/hvc/hvc_xen.c
++++ b/drivers/tty/hvc/hvc_xen.c
+@@ -65,17 +65,22 @@ static DEFINE_SPINLOCK(xencons_lock);
+ static struct xencons_info *vtermno_to_xencons(int vtermno)
+ {
+-      struct xencons_info *entry, *n, *ret = NULL;
++      struct xencons_info *entry, *ret = NULL;
++      unsigned long flags;
+-      if (list_empty(&xenconsoles))
+-                      return NULL;
++      spin_lock_irqsave(&xencons_lock, flags);
++      if (list_empty(&xenconsoles)) {
++              spin_unlock_irqrestore(&xencons_lock, flags);
++              return NULL;
++      }
+-      list_for_each_entry_safe(entry, n, &xenconsoles, list) {
++      list_for_each_entry(entry, &xenconsoles, list) {
+               if (entry->vtermno == vtermno) {
+                       ret  = entry;
+                       break;
+               }
+       }
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return ret;
+ }
+@@ -236,7 +241,7 @@ static int xen_hvm_console_init(void)
+ {
+       int r;
+       uint64_t v = 0;
+-      unsigned long gfn;
++      unsigned long gfn, flags;
+       struct xencons_info *info;
+       if (!xen_hvm_domain())
+@@ -271,9 +276,9 @@ static int xen_hvm_console_init(void)
+               goto err;
+       info->vtermno = HVC_COOKIE;
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       list_add_tail(&info->list, &xenconsoles);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return 0;
+ err:
+@@ -296,6 +301,7 @@ static int xencons_info_pv_init(struct xencons_info *info, int vtermno)
+ static int xen_pv_console_init(void)
+ {
+       struct xencons_info *info;
++      unsigned long flags;
+       if (!xen_pv_domain())
+               return -ENODEV;
+@@ -312,9 +318,9 @@ static int xen_pv_console_init(void)
+               /* already configured */
+               return 0;
+       }
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       xencons_info_pv_init(info, HVC_COOKIE);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return 0;
+ }
+@@ -322,6 +328,7 @@ static int xen_pv_console_init(void)
+ static int xen_initial_domain_console_init(void)
+ {
+       struct xencons_info *info;
++      unsigned long flags;
+       if (!xen_initial_domain())
+               return -ENODEV;
+@@ -336,9 +343,9 @@ static int xen_initial_domain_console_init(void)
+       info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
+       info->vtermno = HVC_COOKIE;
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       list_add_tail(&info->list, &xenconsoles);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return 0;
+ }
+@@ -393,10 +400,12 @@ static void xencons_free(struct xencons_info *info)
+ static int xen_console_remove(struct xencons_info *info)
+ {
++      unsigned long flags;
++
+       xencons_disconnect_backend(info);
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       list_del(&info->list);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       if (info->xbdev != NULL)
+               xencons_free(info);
+       else {
+@@ -477,6 +486,7 @@ static int xencons_probe(struct xenbus_device *dev,
+ {
+       int ret, devid;
+       struct xencons_info *info;
++      unsigned long flags;
+       devid = dev->nodename[strlen(dev->nodename) - 1] - '0';
+       if (devid == 0)
+@@ -495,9 +505,9 @@ static int xencons_probe(struct xenbus_device *dev,
+       ret = xencons_connect_backend(dev, info);
+       if (ret < 0)
+               goto error;
+-      spin_lock(&xencons_lock);
++      spin_lock_irqsave(&xencons_lock, flags);
+       list_add_tail(&info->list, &xenconsoles);
+-      spin_unlock(&xencons_lock);
++      spin_unlock_irqrestore(&xencons_lock, flags);
+       return 0;
+@@ -596,10 +606,12 @@ static int __init xen_hvc_init(void)
+       info->hvc = hvc_alloc(HVC_COOKIE, info->irq, ops, 256);
+       if (IS_ERR(info->hvc)) {
++              unsigned long flags;
++
+               r = PTR_ERR(info->hvc);
+-              spin_lock(&xencons_lock);
++              spin_lock_irqsave(&xencons_lock, flags);
+               list_del(&info->list);
+-              spin_unlock(&xencons_lock);
++              spin_unlock_irqrestore(&xencons_lock, flags);
+               if (info->irq)
+                       unbind_from_irqhandler(info->irq, NULL);
+               kfree(info);
+-- 
+2.35.1
+
diff --git a/queue-4.14/nfc-pn533-wait-for-out_urb-s-completion-in-pn533_usb.patch b/queue-4.14/nfc-pn533-wait-for-out_urb-s-completion-in-pn533_usb.patch
new file mode 100644 (file)
index 0000000..d11ea20
--- /dev/null
@@ -0,0 +1,129 @@
+From 6dcc32c9ada6194d35a8e10dd33ba3353a735918 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 6 Jan 2023 17:23:44 +0900
+Subject: nfc: pn533: Wait for out_urb's completion in pn533_usb_send_frame()
+
+From: Minsuk Kang <linuxlovemin@yonsei.ac.kr>
+
+[ Upstream commit 9dab880d675b9d0dd56c6428e4e8352a3339371d ]
+
+Fix a use-after-free that occurs in hcd when in_urb sent from
+pn533_usb_send_frame() is completed earlier than out_urb. Its callback
+frees the skb data in pn533_send_async_complete() that is used as a
+transfer buffer of out_urb. Wait before sending in_urb until the
+callback of out_urb is called. To modify the callback of out_urb alone,
+separate the complete function of out_urb and ack_urb.
+
+Found by a modified version of syzkaller.
+
+BUG: KASAN: use-after-free in dummy_timer
+Call Trace:
+ memcpy (mm/kasan/shadow.c:65)
+ dummy_perform_transfer (drivers/usb/gadget/udc/dummy_hcd.c:1352)
+ transfer (drivers/usb/gadget/udc/dummy_hcd.c:1453)
+ dummy_timer (drivers/usb/gadget/udc/dummy_hcd.c:1972)
+ arch_static_branch (arch/x86/include/asm/jump_label.h:27)
+ static_key_false (include/linux/jump_label.h:207)
+ timer_expire_exit (include/trace/events/timer.h:127)
+ call_timer_fn (kernel/time/timer.c:1475)
+ expire_timers (kernel/time/timer.c:1519)
+ __run_timers (kernel/time/timer.c:1790)
+ run_timer_softirq (kernel/time/timer.c:1803)
+
+Fixes: c46ee38620a2 ("NFC: pn533: add NXP pn533 nfc device driver")
+Signed-off-by: Minsuk Kang <linuxlovemin@yonsei.ac.kr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/nfc/pn533/usb.c | 44 ++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 41 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c
+index a2c9b3f3bc23..c7da364b6358 100644
+--- a/drivers/nfc/pn533/usb.c
++++ b/drivers/nfc/pn533/usb.c
+@@ -165,10 +165,17 @@ static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags)
+       return usb_submit_urb(phy->ack_urb, flags);
+ }
++struct pn533_out_arg {
++      struct pn533_usb_phy *phy;
++      struct completion done;
++};
++
+ static int pn533_usb_send_frame(struct pn533 *dev,
+                               struct sk_buff *out)
+ {
+       struct pn533_usb_phy *phy = dev->phy;
++      struct pn533_out_arg arg;
++      void *cntx;
+       int rc;
+       if (phy->priv == NULL)
+@@ -180,10 +187,17 @@ static int pn533_usb_send_frame(struct pn533 *dev,
+       print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
+                            out->data, out->len, false);
++      init_completion(&arg.done);
++      cntx = phy->out_urb->context;
++      phy->out_urb->context = &arg;
++
+       rc = usb_submit_urb(phy->out_urb, GFP_KERNEL);
+       if (rc)
+               return rc;
++      wait_for_completion(&arg.done);
++      phy->out_urb->context = cntx;
++
+       if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
+               /* request for response for sent packet directly */
+               rc = pn533_submit_urb_for_response(phy, GFP_KERNEL);
+@@ -424,7 +438,31 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
+       return arg.rc;
+ }
+-static void pn533_send_complete(struct urb *urb)
++static void pn533_out_complete(struct urb *urb)
++{
++      struct pn533_out_arg *arg = urb->context;
++      struct pn533_usb_phy *phy = arg->phy;
++
++      switch (urb->status) {
++      case 0:
++              break; /* success */
++      case -ECONNRESET:
++      case -ENOENT:
++              dev_dbg(&phy->udev->dev,
++                      "The urb has been stopped (status %d)\n",
++                      urb->status);
++              break;
++      case -ESHUTDOWN:
++      default:
++              nfc_err(&phy->udev->dev,
++                      "Urb failure (status %d)\n",
++                      urb->status);
++      }
++
++      complete(&arg->done);
++}
++
++static void pn533_ack_complete(struct urb *urb)
+ {
+       struct pn533_usb_phy *phy = urb->context;
+@@ -512,10 +550,10 @@ static int pn533_usb_probe(struct usb_interface *interface,
+       usb_fill_bulk_urb(phy->out_urb, phy->udev,
+                         usb_sndbulkpipe(phy->udev, out_endpoint),
+-                        NULL, 0, pn533_send_complete, phy);
++                        NULL, 0, pn533_out_complete, phy);
+       usb_fill_bulk_urb(phy->ack_urb, phy->udev,
+                         usb_sndbulkpipe(phy->udev, out_endpoint),
+-                        NULL, 0, pn533_send_complete, phy);
++                        NULL, 0, pn533_ack_complete, phy);
+       switch (id->driver_info) {
+       case PN533_DEVICE_STD:
+-- 
+2.35.1
+
diff --git a/queue-4.14/regulator-da9211-use-irq-handler-when-ready.patch b/queue-4.14/regulator-da9211-use-irq-handler-when-ready.patch
new file mode 100644 (file)
index 0000000..46f0219
--- /dev/null
@@ -0,0 +1,66 @@
+From 65178d5bf966dfc8bb905fb123591e9e471b0463 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 27 Nov 2022 22:06:02 +0100
+Subject: regulator: da9211: Use irq handler when ready
+
+From: Ricardo Ribalda <ribalda@chromium.org>
+
+[ Upstream commit 02228f6aa6a64d588bc31e3267d05ff184d772eb ]
+
+If the system does not come from reset (like when it is kexec()), the
+regulator might have an IRQ waiting for us.
+
+If we enable the IRQ handler before its structures are ready, we crash.
+
+This patch fixes:
+
+[    1.141839] Unable to handle kernel read from unreadable memory at virtual address 0000000000000078
+[    1.316096] Call trace:
+[    1.316101]  blocking_notifier_call_chain+0x20/0xa8
+[    1.322757] cpu cpu0: dummy supplies not allowed for exclusive requests
+[    1.327823]  regulator_notifier_call_chain+0x1c/0x2c
+[    1.327825]  da9211_irq_handler+0x68/0xf8
+[    1.327829]  irq_thread+0x11c/0x234
+[    1.327833]  kthread+0x13c/0x154
+
+Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
+Reviewed-by: Adam Ward <DLG-Adam.Ward.opensource@dm.renesas.com>
+Link: https://lore.kernel.org/r/20221124-da9211-v2-0-1779e3c5d491@chromium.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/regulator/da9211-regulator.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
+index aa47280efd32..8879e315211e 100644
+--- a/drivers/regulator/da9211-regulator.c
++++ b/drivers/regulator/da9211-regulator.c
+@@ -470,6 +470,12 @@ static int da9211_i2c_probe(struct i2c_client *i2c,
+       chip->chip_irq = i2c->irq;
++      ret = da9211_regulator_init(chip);
++      if (ret < 0) {
++              dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret);
++              return ret;
++      }
++
+       if (chip->chip_irq != 0) {
+               ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL,
+                                       da9211_irq_handler,
+@@ -484,11 +490,6 @@ static int da9211_i2c_probe(struct i2c_client *i2c,
+               dev_warn(chip->dev, "No IRQ configured\n");
+       }
+-      ret = da9211_regulator_init(chip);
+-
+-      if (ret < 0)
+-              dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret);
+-
+       return ret;
+ }
+-- 
+2.35.1
+
index e572d8d1324fb8ec526ba2852e26372ee2c1e044..2afe614c5274bf01d82aacb4fb7c379124d617a2 100644 (file)
@@ -332,3 +332,6 @@ ipv6-raw-deduct-extension-header-length-in-rawv6_push_pending_frames.patch
 netfilter-ipset-fix-overflow-before-widen-in-the-bitmap_ip_create-function.patch
 x86-boot-avoid-using-intel-mnemonics-in-at-t-syntax-asm.patch
 edac-device-fix-period-calculation-in-edac_device_reset_delay_period.patch
+regulator-da9211-use-irq-handler-when-ready.patch
+hvc-xen-lock-console-list-traversal.patch
+nfc-pn533-wait-for-out_urb-s-completion-in-pn533_usb.patch