]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Mar 2021 12:58:19 +0000 (13:58 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Mar 2021 12:58:19 +0000 (13:58 +0100)
added patches:
floppy-reintroduce-o_ndelay-fix.patch
libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch
mm-hugetlb-fix-a-race-between-freeing-and-dissolving-the-page.patch
usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch

queue-4.4/floppy-reintroduce-o_ndelay-fix.patch [new file with mode: 0644]
queue-4.4/libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch [new file with mode: 0644]
queue-4.4/mm-hugetlb-fix-a-race-between-freeing-and-dissolving-the-page.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch [new file with mode: 0644]

diff --git a/queue-4.4/floppy-reintroduce-o_ndelay-fix.patch b/queue-4.4/floppy-reintroduce-o_ndelay-fix.patch
new file mode 100644 (file)
index 0000000..59d11ef
--- /dev/null
@@ -0,0 +1,81 @@
+From 8a0c014cd20516ade9654fc13b51345ec58e7be8 Mon Sep 17 00:00:00 2001
+From: Jiri Kosina <jkosina@suse.cz>
+Date: Fri, 22 Jan 2021 12:13:20 +0100
+Subject: floppy: reintroduce O_NDELAY fix
+
+From: Jiri Kosina <jkosina@suse.cz>
+
+commit 8a0c014cd20516ade9654fc13b51345ec58e7be8 upstream.
+
+This issue was originally fixed in 09954bad4 ("floppy: refactor open()
+flags handling").
+
+The fix as a side-effect, however, introduce issue for open(O_ACCMODE)
+that is being used for ioctl-only open. I wrote a fix for that, but
+instead of it being merged, full revert of 09954bad4 was performed,
+re-introducing the O_NDELAY / O_NONBLOCK issue, and it strikes again.
+
+This is a forward-port of the original fix to current codebase; the
+original submission had the changelog below:
+
+====
+Commit 09954bad4 ("floppy: refactor open() flags handling"), as a
+side-effect, causes open(/dev/fdX, O_ACCMODE) to fail. It turns out that
+this is being used setfdprm userspace for ioctl-only open().
+
+Reintroduce back the original behavior wrt !(FMODE_READ|FMODE_WRITE)
+modes, while still keeping the original O_NDELAY bug fixed.
+
+Link: https://lore.kernel.org/r/nycvar.YFH.7.76.2101221209060.5622@cbobk.fhfr.pm
+Cc: stable@vger.kernel.org
+Reported-by: Wim Osterholt <wim@djo.tudelft.nl>
+Tested-by: Wim Osterholt <wim@djo.tudelft.nl>
+Reported-and-tested-by: Kurt Garloff <kurt@garloff.de>
+Fixes: 09954bad4 ("floppy: refactor open() flags handling")
+Fixes: f2791e7ead ("Revert "floppy: refactor open() flags handling"")
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Denis Efremov <efremov@linux.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/block/floppy.c |   27 ++++++++++++++-------------
+ 1 file changed, 14 insertions(+), 13 deletions(-)
+
+--- a/drivers/block/floppy.c
++++ b/drivers/block/floppy.c
+@@ -4066,21 +4066,22 @@ static int floppy_open(struct block_devi
+       if (UFDCS->rawcmd == 1)
+               UFDCS->rawcmd = 2;
+-      if (!(mode & FMODE_NDELAY)) {
+-              if (mode & (FMODE_READ|FMODE_WRITE)) {
+-                      UDRS->last_checked = 0;
+-                      clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
+-                      check_disk_change(bdev);
+-                      if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
+-                              goto out;
+-                      if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
+-                              goto out;
+-              }
+-              res = -EROFS;
+-              if ((mode & FMODE_WRITE) &&
+-                  !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags))
++      if (mode & (FMODE_READ|FMODE_WRITE)) {
++              UDRS->last_checked = 0;
++              clear_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags);
++              check_disk_change(bdev);
++              if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags))
++                      goto out;
++              if (test_bit(FD_OPEN_SHOULD_FAIL_BIT, &UDRS->flags))
+                       goto out;
+       }
++
++      res = -EROFS;
++
++      if ((mode & FMODE_WRITE) &&
++                      !test_bit(FD_DISK_WRITABLE_BIT, &UDRS->flags))
++              goto out;
++
+       mutex_unlock(&open_lock);
+       mutex_unlock(&floppy_mutex);
+       return 0;
diff --git a/queue-4.4/libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch b/queue-4.4/libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch
new file mode 100644 (file)
index 0000000..e2dff04
--- /dev/null
@@ -0,0 +1,98 @@
+From foo@baz Mon Mar  1 01:45:42 PM CET 2021
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Mon, 1 Feb 2021 16:20:40 -0800
+Subject: libnvdimm/dimm: Avoid race between probe and available_slots_show()
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit 7018c897c2f243d4b5f1b94bc6b4831a7eab80fb upstream
+
+Richard reports that the following test:
+
+(while true; do
+     cat /sys/bus/nd/devices/nmem*/available_slots 2>&1 > /dev/null
+ done) &
+
+while true; do
+     for i in $(seq 0 4); do
+         echo nmem$i > /sys/bus/nd/drivers/nvdimm/bind
+     done
+     for i in $(seq 0 4); do
+         echo nmem$i > /sys/bus/nd/drivers/nvdimm/unbind
+     done
+ done
+
+...fails with a crash signature like:
+
+    divide error: 0000 [#1] SMP KASAN PTI
+    RIP: 0010:nd_label_nfree+0x134/0x1a0 [libnvdimm]
+    [..]
+    Call Trace:
+     available_slots_show+0x4e/0x120 [libnvdimm]
+     dev_attr_show+0x42/0x80
+     ? memset+0x20/0x40
+     sysfs_kf_seq_show+0x218/0x410
+
+The root cause is that available_slots_show() consults driver-data, but
+fails to synchronize against device-unbind setting up a TOCTOU race to
+access uninitialized memory.
+
+Validate driver-data under the device-lock.
+
+Fixes: 4d88a97aa9e8 ("libnvdimm, nvdimm: dimm driver and base libnvdimm device-driver infrastructure")
+Cc: <stable@vger.kernel.org>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Dave Jiang <dave.jiang@intel.com>
+Cc: Ira Weiny <ira.weiny@intel.com>
+Cc: Coly Li <colyli@suse.com>
+Reported-by: Richard Palethorpe <rpalethorpe@suse.com>
+Acked-by: Richard Palethorpe <rpalethorpe@suse.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+[sudip: use device_lock()]
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/nvdimm/dimm_devs.c |   18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+--- a/drivers/nvdimm/dimm_devs.c
++++ b/drivers/nvdimm/dimm_devs.c
+@@ -303,16 +303,16 @@ static ssize_t state_show(struct device
+ }
+ static DEVICE_ATTR_RO(state);
+-static ssize_t available_slots_show(struct device *dev,
+-              struct device_attribute *attr, char *buf)
++static ssize_t __available_slots_show(struct nvdimm_drvdata *ndd, char *buf)
+ {
+-      struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
++      struct device *dev;
+       ssize_t rc;
+       u32 nfree;
+       if (!ndd)
+               return -ENXIO;
++      dev = ndd->dev;
+       nvdimm_bus_lock(dev);
+       nfree = nd_label_nfree(ndd);
+       if (nfree - 1 > nfree) {
+@@ -324,6 +324,18 @@ static ssize_t available_slots_show(stru
+       nvdimm_bus_unlock(dev);
+       return rc;
+ }
++
++static ssize_t available_slots_show(struct device *dev,
++                                  struct device_attribute *attr, char *buf)
++{
++      ssize_t rc;
++
++      device_lock(dev);
++      rc = __available_slots_show(dev_get_drvdata(dev), buf);
++      device_unlock(dev);
++
++      return rc;
++}
+ static DEVICE_ATTR_RO(available_slots);
+ static struct attribute *nvdimm_attributes[] = {
diff --git a/queue-4.4/mm-hugetlb-fix-a-race-between-freeing-and-dissolving-the-page.patch b/queue-4.4/mm-hugetlb-fix-a-race-between-freeing-and-dissolving-the-page.patch
new file mode 100644 (file)
index 0000000..05b186b
--- /dev/null
@@ -0,0 +1,136 @@
+From foo@baz Mon Mar  1 01:42:07 PM CET 2021
+From: Muchun Song <songmuchun@bytedance.com>
+Date: Thu, 4 Feb 2021 18:32:06 -0800
+Subject: mm: hugetlb: fix a race between freeing and dissolving the page
+
+From: Muchun Song <songmuchun@bytedance.com>
+
+commit 7ffddd499ba6122b1a07828f023d1d67629aa017 upstream
+
+There is a race condition between __free_huge_page()
+and dissolve_free_huge_page().
+
+  CPU0:                         CPU1:
+
+  // page_count(page) == 1
+  put_page(page)
+    __free_huge_page(page)
+                                dissolve_free_huge_page(page)
+                                  spin_lock(&hugetlb_lock)
+                                  // PageHuge(page) && !page_count(page)
+                                  update_and_free_page(page)
+                                  // page is freed to the buddy
+                                  spin_unlock(&hugetlb_lock)
+      spin_lock(&hugetlb_lock)
+      clear_page_huge_active(page)
+      enqueue_huge_page(page)
+      // It is wrong, the page is already freed
+      spin_unlock(&hugetlb_lock)
+
+The race window is between put_page() and dissolve_free_huge_page().
+
+We should make sure that the page is already on the free list when it is
+dissolved.
+
+As a result __free_huge_page would corrupt page(s) already in the buddy
+allocator.
+
+Link: https://lkml.kernel.org/r/20210115124942.46403-4-songmuchun@bytedance.com
+Fixes: c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle hugepage")
+Signed-off-by: Muchun Song <songmuchun@bytedance.com>
+Reviewed-by: Mike Kravetz <mike.kravetz@oracle.com>
+Reviewed-by: Oscar Salvador <osalvador@suse.de>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Yang Shi <shy828301@gmail.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+[sudip: adjust context]
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/hugetlb.c |   39 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 39 insertions(+)
+
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -66,6 +66,21 @@ DEFINE_SPINLOCK(hugetlb_lock);
+ static int num_fault_mutexes;
+ struct mutex *hugetlb_fault_mutex_table ____cacheline_aligned_in_smp;
++static inline bool PageHugeFreed(struct page *head)
++{
++      return page_private(head + 4) == -1UL;
++}
++
++static inline void SetPageHugeFreed(struct page *head)
++{
++      set_page_private(head + 4, -1UL);
++}
++
++static inline void ClearPageHugeFreed(struct page *head)
++{
++      set_page_private(head + 4, 0);
++}
++
+ /* Forward declaration */
+ static int hugetlb_acct_memory(struct hstate *h, long delta);
+@@ -841,6 +856,7 @@ static void enqueue_huge_page(struct hst
+       list_move(&page->lru, &h->hugepage_freelists[nid]);
+       h->free_huge_pages++;
+       h->free_huge_pages_node[nid]++;
++      SetPageHugeFreed(page);
+ }
+ static struct page *dequeue_huge_page_node(struct hstate *h, int nid)
+@@ -858,6 +874,7 @@ static struct page *dequeue_huge_page_no
+               return NULL;
+       list_move(&page->lru, &h->hugepage_activelist);
+       set_page_refcounted(page);
++      ClearPageHugeFreed(page);
+       h->free_huge_pages--;
+       h->free_huge_pages_node[nid]--;
+       return page;
+@@ -1266,6 +1283,7 @@ static void prep_new_huge_page(struct hs
+       set_hugetlb_cgroup(page, NULL);
+       h->nr_huge_pages++;
+       h->nr_huge_pages_node[nid]++;
++      ClearPageHugeFreed(page);
+       spin_unlock(&hugetlb_lock);
+       put_page(page); /* free it into the hugepage allocator */
+ }
+@@ -1424,11 +1442,32 @@ static int free_pool_huge_page(struct hs
+  */
+ static void dissolve_free_huge_page(struct page *page)
+ {
++retry:
+       spin_lock(&hugetlb_lock);
+       if (PageHuge(page) && !page_count(page)) {
+               struct page *head = compound_head(page);
+               struct hstate *h = page_hstate(head);
+               int nid = page_to_nid(head);
++
++              /*
++               * We should make sure that the page is already on the free list
++               * when it is dissolved.
++               */
++              if (unlikely(!PageHugeFreed(head))) {
++                      spin_unlock(&hugetlb_lock);
++                      cond_resched();
++
++                      /*
++                       * Theoretically, we should return -EBUSY when we
++                       * encounter this race. In fact, we have a chance
++                       * to successfully dissolve the page if we do a
++                       * retry. Because the race window is quite small.
++                       * If we seize this opportunity, it is an optimization
++                       * for increasing the success rate of dissolving page.
++                       */
++                      goto retry;
++              }
++
+               list_del(&head->lru);
+               h->free_huge_pages--;
+               h->free_huge_pages_node[nid]--;
index 5a2896e50893fdabff34194d760eedcd862f2d95..526e6ffe7451b8c9841d06339c7fadd0a263ba43 100644 (file)
@@ -74,3 +74,7 @@ btrfs-fix-reloc-root-leak-with-0-ref-reloc-roots-on-recovery.patch
 drivers-misc-vmw_vmci-restrict-too-big-queue-size-in-qp_host_alloc_queue.patch
 staging-rtl8188eu-add-edimax-ew-7811un-v2-to-device-table.patch
 x86-reboot-force-all-cpus-to-exit-vmx-root-if-vmx-is-supported.patch
+floppy-reintroduce-o_ndelay-fix.patch
+mm-hugetlb-fix-a-race-between-freeing-and-dissolving-the-page.patch
+usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch
+libnvdimm-dimm-avoid-race-between-probe-and-available_slots_show.patch
diff --git a/queue-4.4/usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch b/queue-4.4/usb-renesas_usbhs-clear-pipe-running-flag-in-usbhs_pkt_pop.patch
new file mode 100644 (file)
index 0000000..6f99ec7
--- /dev/null
@@ -0,0 +1,37 @@
+From foo@baz Mon Mar  1 01:44:53 PM CET 2021
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Date: Mon, 1 Feb 2021 21:47:20 +0900
+Subject: usb: renesas_usbhs: Clear pipe running flag in usbhs_pkt_pop()
+
+From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+
+commit 9917f0e3cdba7b9f1a23f70e3f70b1a106be54a8 upstream
+
+Should clear the pipe running flag in usbhs_pkt_pop(). Otherwise,
+we cannot use this pipe after dequeue was called while the pipe was
+running.
+
+Fixes: 8355b2b3082d ("usb: renesas_usbhs: fix the behavior of some usbhs_pkt_handle")
+Reported-by: Tho Vu <tho.vu.wh@renesas.com>
+Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
+Link: https://lore.kernel.org/r/1612183640-8898-1-git-send-email-yoshihiro.shimoda.uh@renesas.com
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[sudip: adjust context]
+Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/renesas_usbhs/fifo.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/renesas_usbhs/fifo.c
++++ b/drivers/usb/renesas_usbhs/fifo.c
+@@ -140,6 +140,8 @@ struct usbhs_pkt *usbhs_pkt_pop(struct u
+                       usbhsf_dma_unmap(pkt);
+               }
++              usbhs_pipe_running(pipe, 0);
++
+               __usbhsf_pkt_del(pkt);
+       }