]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
fixes for 4.14
authorSasha Levin <sashal@kernel.org>
Sun, 19 Jan 2020 17:46:14 +0000 (12:46 -0500)
committerSasha Levin <sashal@kernel.org>
Sun, 19 Jan 2020 17:48:11 +0000 (12:48 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-4.14/mm-huge_memory.c-make-__thp_get_unmapped_area-static.patch [new file with mode: 0644]
queue-4.14/mm-huge_memory.c-thp-fix-conflict-of-above-47bit-hin.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/usb-serial-io_edgeport-handle-unbound-ports-on-urb-c.patch [new file with mode: 0644]
queue-4.14/usb-serial-io_edgeport-use-irqsave-in-usb-s-complete.patch [new file with mode: 0644]

diff --git a/queue-4.14/mm-huge_memory.c-make-__thp_get_unmapped_area-static.patch b/queue-4.14/mm-huge_memory.c-make-__thp_get_unmapped_area-static.patch
new file mode 100644 (file)
index 0000000..0b8f97f
--- /dev/null
@@ -0,0 +1,38 @@
+From e6de2f5beaf88f7cdea7b5a435d183539b783d65 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 May 2019 17:23:17 -0700
+Subject: mm/huge_memory.c: make __thp_get_unmapped_area static
+
+From: Bharath Vedartham <linux.bhar@gmail.com>
+
+[ Upstream commit b3b07077b01ecbbd98efede778c195567de25b71 ]
+
+__thp_get_unmapped_area is only used in mm/huge_memory.c.  Make it static.
+Tested by building and booting the kernel.
+
+Link: http://lkml.kernel.org/r/20190504102353.GA22525@bharath12345-Inspiron-5559
+Signed-off-by: Bharath Vedartham <linux.bhar@gmail.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/huge_memory.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/mm/huge_memory.c b/mm/huge_memory.c
+index 1adc2e6c50f9..6d835535946d 100644
+--- a/mm/huge_memory.c
++++ b/mm/huge_memory.c
+@@ -502,7 +502,7 @@ void prep_transhuge_page(struct page *page)
+       set_compound_page_dtor(page, TRANSHUGE_PAGE_DTOR);
+ }
+-unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long len,
++static unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long len,
+               loff_t off, unsigned long flags, unsigned long size)
+ {
+       unsigned long addr;
+-- 
+2.20.1
+
diff --git a/queue-4.14/mm-huge_memory.c-thp-fix-conflict-of-above-47bit-hin.patch b/queue-4.14/mm-huge_memory.c-thp-fix-conflict-of-above-47bit-hin.patch
new file mode 100644 (file)
index 0000000..0e138b2
--- /dev/null
@@ -0,0 +1,139 @@
+From c2c0078b764a5968f668b223c21c276bb99cf8d9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jan 2020 16:29:10 -0800
+Subject: mm/huge_memory.c: thp: fix conflict of above-47bit hint address and
+ PMD alignment
+
+From: Kirill A. Shutemov <kirill@shutemov.name>
+
+[ Upstream commit 97d3d0f9a1cf132c63c0b8b8bd497b8a56283dd9 ]
+
+Patch series "Fix two above-47bit hint address vs.  THP bugs".
+
+The two get_unmapped_area() implementations have to be fixed to provide
+THP-friendly mappings if above-47bit hint address is specified.
+
+This patch (of 2):
+
+Filesystems use thp_get_unmapped_area() to provide THP-friendly
+mappings.  For DAX in particular.
+
+Normally, the kernel doesn't create userspace mappings above 47-bit,
+even if the machine allows this (such as with 5-level paging on x86-64).
+Not all user space is ready to handle wide addresses.  It's known that
+at least some JIT compilers use higher bits in pointers to encode their
+information.
+
+Userspace can ask for allocation from full address space by specifying
+hint address (with or without MAP_FIXED) above 47-bits.  If the
+application doesn't need a particular address, but wants to allocate
+from whole address space it can specify -1 as a hint address.
+
+Unfortunately, this trick breaks thp_get_unmapped_area(): the function
+would not try to allocate PMD-aligned area if *any* hint address
+specified.
+
+Modify the routine to handle it correctly:
+
+ - Try to allocate the space at the specified hint address with length
+   padding required for PMD alignment.
+ - If failed, retry without length padding (but with the same hint
+   address);
+ - If the returned address matches the hint address return it.
+ - Otherwise, align the address as required for THP and return.
+
+The user specified hint address is passed down to get_unmapped_area() so
+above-47bit hint address will be taken into account without breaking
+alignment requirements.
+
+Link: http://lkml.kernel.org/r/20191220142548.7118-2-kirill.shutemov@linux.intel.com
+Fixes: b569bab78d8d ("x86/mm: Prepare to expose larger address space to userspace")
+Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
+Reported-by: Thomas Willhalm <thomas.willhalm@intel.com>
+Tested-by: Dan Williams <dan.j.williams@intel.com>
+Cc: "Aneesh Kumar K . V" <aneesh.kumar@linux.vnet.ibm.com>
+Cc: "Bruggeman, Otto G" <otto.g.bruggeman@intel.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/huge_memory.c | 38 ++++++++++++++++++++++++--------------
+ 1 file changed, 24 insertions(+), 14 deletions(-)
+
+diff --git a/mm/huge_memory.c b/mm/huge_memory.c
+index 6d835535946d..92915cc87549 100644
+--- a/mm/huge_memory.c
++++ b/mm/huge_memory.c
+@@ -502,13 +502,13 @@ void prep_transhuge_page(struct page *page)
+       set_compound_page_dtor(page, TRANSHUGE_PAGE_DTOR);
+ }
+-static unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long len,
++static unsigned long __thp_get_unmapped_area(struct file *filp,
++              unsigned long addr, unsigned long len,
+               loff_t off, unsigned long flags, unsigned long size)
+ {
+-      unsigned long addr;
+       loff_t off_end = off + len;
+       loff_t off_align = round_up(off, size);
+-      unsigned long len_pad;
++      unsigned long len_pad, ret;
+       if (off_end <= off_align || (off_end - off_align) < size)
+               return 0;
+@@ -517,30 +517,40 @@ static unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long le
+       if (len_pad < len || (off + len_pad) < off)
+               return 0;
+-      addr = current->mm->get_unmapped_area(filp, 0, len_pad,
++      ret = current->mm->get_unmapped_area(filp, addr, len_pad,
+                                             off >> PAGE_SHIFT, flags);
+-      if (IS_ERR_VALUE(addr))
++
++      /*
++       * The failure might be due to length padding. The caller will retry
++       * without the padding.
++       */
++      if (IS_ERR_VALUE(ret))
+               return 0;
+-      addr += (off - addr) & (size - 1);
+-      return addr;
++      /*
++       * Do not try to align to THP boundary if allocation at the address
++       * hint succeeds.
++       */
++      if (ret == addr)
++              return addr;
++
++      ret += (off - ret) & (size - 1);
++      return ret;
+ }
+ unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
+               unsigned long len, unsigned long pgoff, unsigned long flags)
+ {
++      unsigned long ret;
+       loff_t off = (loff_t)pgoff << PAGE_SHIFT;
+-      if (addr)
+-              goto out;
+       if (!IS_DAX(filp->f_mapping->host) || !IS_ENABLED(CONFIG_FS_DAX_PMD))
+               goto out;
+-      addr = __thp_get_unmapped_area(filp, len, off, flags, PMD_SIZE);
+-      if (addr)
+-              return addr;
+-
+- out:
++      ret = __thp_get_unmapped_area(filp, addr, len, off, flags, PMD_SIZE);
++      if (ret)
++              return ret;
++out:
+       return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
+ }
+ EXPORT_SYMBOL_GPL(thp_get_unmapped_area);
+-- 
+2.20.1
+
index e1488105a98cd5de381786b44a6d4abefb8c7276..053415351e07660fdfb0506333d2da8396a3fa27 100644 (file)
@@ -28,3 +28,7 @@ btrfs-fix-memory-leak-in-qgroup-accounting.patch
 mm-page-writeback.c-avoid-potential-division-by-zero-in-wb_min_max_ratio.patch
 net-stmmac-16kb-buffer-must-be-16-byte-aligned.patch
 net-stmmac-enable-16kb-buffer-size.patch
+usb-serial-io_edgeport-use-irqsave-in-usb-s-complete.patch
+usb-serial-io_edgeport-handle-unbound-ports-on-urb-c.patch
+mm-huge_memory.c-make-__thp_get_unmapped_area-static.patch
+mm-huge_memory.c-thp-fix-conflict-of-above-47bit-hin.patch
diff --git a/queue-4.14/usb-serial-io_edgeport-handle-unbound-ports-on-urb-c.patch b/queue-4.14/usb-serial-io_edgeport-handle-unbound-ports-on-urb-c.patch
new file mode 100644 (file)
index 0000000..2998bb2
--- /dev/null
@@ -0,0 +1,49 @@
+From 8f8b41e3b9e3fdae7c2384598c66b6d87380b404 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Jan 2020 10:50:23 +0100
+Subject: USB: serial: io_edgeport: handle unbound ports on URB completion
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit e37d1aeda737a20b1846a91a3da3f8b0f00cf690 ]
+
+Check for NULL port data in the shared interrupt and bulk completion
+callbacks to avoid dereferencing a NULL pointer in case a device sends
+data for a port device which isn't bound to a driver (e.g. due to a
+malicious device having unexpected endpoints or after an allocation
+failure on port probe).
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable <stable@vger.kernel.org>
+Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/io_edgeport.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
+index 8810de817095..3705b64ab948 100644
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -720,7 +720,7 @@ static void edge_interrupt_callback(struct urb *urb)
+                       if (txCredits) {
+                               port = edge_serial->serial->port[portNumber];
+                               edge_port = usb_get_serial_port_data(port);
+-                              if (edge_port->open) {
++                              if (edge_port && edge_port->open) {
+                                       spin_lock_irqsave(&edge_port->ep_lock,
+                                                         flags);
+                                       edge_port->txCredits += txCredits;
+@@ -1847,7 +1847,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
+                       if (rxLen && edge_serial->rxPort < serial->num_ports) {
+                               port = serial->port[edge_serial->rxPort];
+                               edge_port = usb_get_serial_port_data(port);
+-                              if (edge_port->open) {
++                              if (edge_port && edge_port->open) {
+                                       dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
+                                               __func__, rxLen,
+                                               edge_serial->rxPort);
+-- 
+2.20.1
+
diff --git a/queue-4.14/usb-serial-io_edgeport-use-irqsave-in-usb-s-complete.patch b/queue-4.14/usb-serial-io_edgeport-use-irqsave-in-usb-s-complete.patch
new file mode 100644 (file)
index 0000000..b51d1c5
--- /dev/null
@@ -0,0 +1,99 @@
+From 81936a3ec782d83832124b3f3da55e8139342a68 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 24 Jun 2018 00:32:06 +0200
+Subject: USB: serial: io_edgeport: use irqsave() in USB's complete callback
+
+From: John Ogness <john.ogness@linutronix.de>
+
+[ Upstream commit dd1fae527612543e560e84f2eba4f6ef2006ac55 ]
+
+The USB completion callback does not disable interrupts while acquiring
+the lock. We want to remove the local_irq_disable() invocation from
+__usb_hcd_giveback_urb() and therefore it is required for the callback
+handler to disable the interrupts while acquiring the lock.
+The callback may be invoked either in IRQ or BH context depending on the
+USB host controller.
+Use the _irqsave() variant of the locking primitives.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/serial/io_edgeport.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
+index 467870f504a5..8810de817095 100644
+--- a/drivers/usb/serial/io_edgeport.c
++++ b/drivers/usb/serial/io_edgeport.c
+@@ -652,6 +652,7 @@ static void edge_interrupt_callback(struct urb *urb)
+       struct usb_serial_port *port;
+       unsigned char *data = urb->transfer_buffer;
+       int length = urb->actual_length;
++      unsigned long flags;
+       int bytes_avail;
+       int position;
+       int txCredits;
+@@ -683,7 +684,7 @@ static void edge_interrupt_callback(struct urb *urb)
+               if (length > 1) {
+                       bytes_avail = data[0] | (data[1] << 8);
+                       if (bytes_avail) {
+-                              spin_lock(&edge_serial->es_lock);
++                              spin_lock_irqsave(&edge_serial->es_lock, flags);
+                               edge_serial->rxBytesAvail += bytes_avail;
+                               dev_dbg(dev,
+                                       "%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d\n",
+@@ -706,7 +707,8 @@ static void edge_interrupt_callback(struct urb *urb)
+                                               edge_serial->read_in_progress = false;
+                                       }
+                               }
+-                              spin_unlock(&edge_serial->es_lock);
++                              spin_unlock_irqrestore(&edge_serial->es_lock,
++                                                     flags);
+                       }
+               }
+               /* grab the txcredits for the ports if available */
+@@ -719,9 +721,11 @@ static void edge_interrupt_callback(struct urb *urb)
+                               port = edge_serial->serial->port[portNumber];
+                               edge_port = usb_get_serial_port_data(port);
+                               if (edge_port->open) {
+-                                      spin_lock(&edge_port->ep_lock);
++                                      spin_lock_irqsave(&edge_port->ep_lock,
++                                                        flags);
+                                       edge_port->txCredits += txCredits;
+-                                      spin_unlock(&edge_port->ep_lock);
++                                      spin_unlock_irqrestore(&edge_port->ep_lock,
++                                                             flags);
+                                       dev_dbg(dev, "%s - txcredits for port%d = %d\n",
+                                               __func__, portNumber,
+                                               edge_port->txCredits);
+@@ -762,6 +766,7 @@ static void edge_bulk_in_callback(struct urb *urb)
+       int                     retval;
+       __u16                   raw_data_length;
+       int status = urb->status;
++      unsigned long flags;
+       if (status) {
+               dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n",
+@@ -781,7 +786,7 @@ static void edge_bulk_in_callback(struct urb *urb)
+       usb_serial_debug_data(dev, __func__, raw_data_length, data);
+-      spin_lock(&edge_serial->es_lock);
++      spin_lock_irqsave(&edge_serial->es_lock, flags);
+       /* decrement our rxBytes available by the number that we just got */
+       edge_serial->rxBytesAvail -= raw_data_length;
+@@ -805,7 +810,7 @@ static void edge_bulk_in_callback(struct urb *urb)
+               edge_serial->read_in_progress = false;
+       }
+-      spin_unlock(&edge_serial->es_lock);
++      spin_unlock_irqrestore(&edge_serial->es_lock, flags);
+ }
+-- 
+2.20.1
+