From: Greg Kroah-Hartman Date: Mon, 15 Nov 2021 12:28:17 +0000 (+0100) Subject: 4.4-stable patches X-Git-Tag: v5.4.160~72 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a4fba1f2548126d86140aa5c87db1a94c5f595f5;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: fuse-fix-page-stealing.patch usb-chipidea-fix-interrupt-deadlock.patch --- diff --git a/queue-4.4/fuse-fix-page-stealing.patch b/queue-4.4/fuse-fix-page-stealing.patch new file mode 100644 index 00000000000..33cd2bb38b1 --- /dev/null +++ b/queue-4.4/fuse-fix-page-stealing.patch @@ -0,0 +1,61 @@ +From 712a951025c0667ff00b25afc360f74e639dfabe Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Tue, 2 Nov 2021 11:10:37 +0100 +Subject: fuse: fix page stealing + +From: Miklos Szeredi + +commit 712a951025c0667ff00b25afc360f74e639dfabe upstream. + +It is possible to trigger a crash by splicing anon pipe bufs to the fuse +device. + +The reason for this is that anon_pipe_buf_release() will reuse buf->page if +the refcount is 1, but that page might have already been stolen and its +flags modified (e.g. PG_lru added). + +This happens in the unlikely case of fuse_dev_splice_write() getting around +to calling pipe_buf_release() after a page has been stolen, added to the +page cache and removed from the page cache. + +Fix by calling pipe_buf_release() right after the page was inserted into +the page cache. In this case the page has an elevated refcount so any +release function will know that the page isn't reusable. + +Reported-by: Frank Dinoff +Link: https://lore.kernel.org/r/CAAmZXrsGg2xsP1CK+cbuEMumtrqdvD-NKnWzhNcvn71RV3c1yw@mail.gmail.com/ +Fixes: dd3bb14f44a6 ("fuse: support splice() writing to fuse device") +Cc: # v2.6.35 +Signed-off-by: Miklos Szeredi +Signed-off-by: Greg Kroah-Hartman + +--- + fs/fuse/dev.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +--- a/fs/fuse/dev.c ++++ b/fs/fuse/dev.c +@@ -922,6 +922,13 @@ static int fuse_try_move_page(struct fus + return err; + } + ++ /* ++ * Release while we have extra ref on stolen page. Otherwise ++ * anon_pipe_buf_release() might think the page can be reused. ++ */ ++ buf->ops->release(cs->pipe, buf); ++ buf->ops = NULL; ++ + page_cache_get(newpage); + + if (!(buf->flags & PIPE_BUF_FLAG_LRU)) +@@ -2090,7 +2097,8 @@ static ssize_t fuse_dev_splice_write(str + out_free: + for (idx = 0; idx < nbuf; idx++) { + struct pipe_buffer *buf = &bufs[idx]; +- buf->ops->release(pipe, buf); ++ if (buf->ops) ++ buf->ops->release(pipe, buf); + } + pipe_unlock(pipe); + diff --git a/queue-4.4/series b/queue-4.4/series index 1ba27d67b78..81cb972e2bb 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -106,3 +106,5 @@ bonding-fix-a-use-after-free-problem-when-bond_sysfs.patch llc-fix-out-of-bound-array-index-in-llc_sk_dev_hash.patch nfc-pn533-fix-double-free-when-pn533_fill_fragment_s.patch vsock-prevent-unnecessary-refcnt-inc-for-nonblocking.patch +fuse-fix-page-stealing.patch +usb-chipidea-fix-interrupt-deadlock.patch diff --git a/queue-4.4/usb-chipidea-fix-interrupt-deadlock.patch b/queue-4.4/usb-chipidea-fix-interrupt-deadlock.patch new file mode 100644 index 00000000000..4e055d240e2 --- /dev/null +++ b/queue-4.4/usb-chipidea-fix-interrupt-deadlock.patch @@ -0,0 +1,97 @@ +From 9aaa81c3366e8393a62374e3a1c67c69edc07b8a Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 21 Oct 2021 10:34:47 +0200 +Subject: USB: chipidea: fix interrupt deadlock + +From: Johan Hovold + +commit 9aaa81c3366e8393a62374e3a1c67c69edc07b8a upstream. + +Chipidea core was calling the interrupt handler from non-IRQ context +with interrupts enabled, something which can lead to a deadlock if +there's an actual interrupt trying to take a lock that's already held +(e.g. the controller lock in udc_irq()). + +Add a wrapper that can be used to fake interrupts instead of calling the +handler directly. + +Fixes: 3ecb3e09b042 ("usb: chipidea: Use extcon framework for VBUS and ID detect") +Fixes: 876d4e1e8298 ("usb: chipidea: core: add wakeup support for extcon") +Cc: Peter Chen +Cc: stable@vger.kernel.org # 4.4 +Signed-off-by: Johan Hovold +Link: https://lore.kernel.org/r/20211021083447.20078-1-johan@kernel.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/chipidea/core.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +--- a/drivers/usb/chipidea/core.c ++++ b/drivers/usb/chipidea/core.c +@@ -518,7 +518,7 @@ int hw_device_reset(struct ci_hdrc *ci) + return 0; + } + +-static irqreturn_t ci_irq(int irq, void *data) ++static irqreturn_t ci_irq_handler(int irq, void *data) + { + struct ci_hdrc *ci = data; + irqreturn_t ret = IRQ_NONE; +@@ -571,6 +571,15 @@ static irqreturn_t ci_irq(int irq, void + return ret; + } + ++static void ci_irq(struct ci_hdrc *ci) ++{ ++ unsigned long flags; ++ ++ local_irq_save(flags); ++ ci_irq_handler(ci->irq, ci); ++ local_irq_restore(flags); ++} ++ + static int ci_vbus_notifier(struct notifier_block *nb, unsigned long event, + void *ptr) + { +@@ -584,7 +593,7 @@ static int ci_vbus_notifier(struct notif + + vbus->changed = true; + +- ci_irq(ci->irq, ci); ++ ci_irq(ci); + return NOTIFY_DONE; + } + +@@ -601,7 +610,7 @@ static int ci_id_notifier(struct notifie + + id->changed = true; + +- ci_irq(ci->irq, ci); ++ ci_irq(ci); + return NOTIFY_DONE; + } + +@@ -1023,7 +1032,7 @@ static int ci_hdrc_probe(struct platform + } + + platform_set_drvdata(pdev, ci); +- ret = devm_request_irq(dev, ci->irq, ci_irq, IRQF_SHARED, ++ ret = devm_request_irq(dev, ci->irq, ci_irq_handler, IRQF_SHARED, + ci->platdata->name, ci); + if (ret) + goto stop; +@@ -1138,11 +1147,11 @@ static void ci_extcon_wakeup_int(struct + + if (!IS_ERR(cable_id->edev) && ci->is_otg && + (otgsc & OTGSC_IDIE) && (otgsc & OTGSC_IDIS)) +- ci_irq(ci->irq, ci); ++ ci_irq(ci); + + if (!IS_ERR(cable_vbus->edev) && ci->is_otg && + (otgsc & OTGSC_BSVIE) && (otgsc & OTGSC_BSVIS)) +- ci_irq(ci->irq, ci); ++ ci_irq(ci); + } + + static int ci_controller_resume(struct device *dev)