]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 14 Dec 2017 17:48:27 +0000 (18:48 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 14 Dec 2017 17:48:27 +0000 (18:48 +0100)
added patches:
fcntl-don-t-cap-l_start-and-l_end-values-for-f_getlk64-in-compat-syscall.patch
ipmi-stop-timers-before-cleaning-up-the-module.patch
usb-gadget-ffs-forbid-usb_ep_alloc_request-from-sleeping.patch

queue-4.14/fcntl-don-t-cap-l_start-and-l_end-values-for-f_getlk64-in-compat-syscall.patch [new file with mode: 0644]
queue-4.14/ipmi-stop-timers-before-cleaning-up-the-module.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/usb-gadget-ffs-forbid-usb_ep_alloc_request-from-sleeping.patch [new file with mode: 0644]

diff --git a/queue-4.14/fcntl-don-t-cap-l_start-and-l_end-values-for-f_getlk64-in-compat-syscall.patch b/queue-4.14/fcntl-don-t-cap-l_start-and-l_end-values-for-f_getlk64-in-compat-syscall.patch
new file mode 100644 (file)
index 0000000..b2b8301
--- /dev/null
@@ -0,0 +1,143 @@
+From 4d2dc2cc766c3b51929658cacbc6e34fc8e242fb Mon Sep 17 00:00:00 2001
+From: Jeff Layton <jlayton@redhat.com>
+Date: Tue, 14 Nov 2017 14:42:57 -0500
+Subject: fcntl: don't cap l_start and l_end values for F_GETLK64 in compat syscall
+
+From: Jeff Layton <jlayton@redhat.com>
+
+commit 4d2dc2cc766c3b51929658cacbc6e34fc8e242fb upstream.
+
+Currently, we're capping the values too low in the F_GETLK64 case. The
+fields in that structure are 64-bit values, so we shouldn't need to do
+any sort of fixup there.
+
+Make sure we check that assumption at build time in the future however
+by ensuring that the sizes we're copying will fit.
+
+With this, we no longer need COMPAT_LOFF_T_MAX either, so remove it.
+
+Fixes: 94073ad77fff2 (fs/locks: don't mess with the address limit in compat_fcntl64)
+Reported-by: Vitaly Lipatov <lav@etersoft.ru>
+Signed-off-by: Jeff Layton <jlayton@redhat.com>
+Reviewed-by: David Howells <dhowells@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/compat.h   |    1 -
+ arch/mips/include/asm/compat.h    |    1 -
+ arch/parisc/include/asm/compat.h  |    1 -
+ arch/powerpc/include/asm/compat.h |    1 -
+ arch/s390/include/asm/compat.h    |    1 -
+ arch/sparc/include/asm/compat.h   |    1 -
+ arch/tile/include/asm/compat.h    |    1 -
+ arch/x86/include/asm/compat.h     |    1 -
+ fs/fcntl.c                        |   11 +++++------
+ 9 files changed, 5 insertions(+), 14 deletions(-)
+
+--- a/arch/arm64/include/asm/compat.h
++++ b/arch/arm64/include/asm/compat.h
+@@ -215,7 +215,6 @@ typedef struct compat_siginfo {
+ } compat_siginfo_t;
+ #define COMPAT_OFF_T_MAX      0x7fffffff
+-#define COMPAT_LOFF_T_MAX     0x7fffffffffffffffL
+ /*
+  * A pointer passed in from user mode. This should not
+--- a/arch/mips/include/asm/compat.h
++++ b/arch/mips/include/asm/compat.h
+@@ -200,7 +200,6 @@ typedef struct compat_siginfo {
+ } compat_siginfo_t;
+ #define COMPAT_OFF_T_MAX      0x7fffffff
+-#define COMPAT_LOFF_T_MAX     0x7fffffffffffffffL
+ /*
+  * A pointer passed in from user mode. This should not
+--- a/arch/parisc/include/asm/compat.h
++++ b/arch/parisc/include/asm/compat.h
+@@ -195,7 +195,6 @@ typedef struct compat_siginfo {
+ } compat_siginfo_t;
+ #define COMPAT_OFF_T_MAX      0x7fffffff
+-#define COMPAT_LOFF_T_MAX     0x7fffffffffffffffL
+ struct compat_ipc64_perm {
+       compat_key_t key;
+--- a/arch/powerpc/include/asm/compat.h
++++ b/arch/powerpc/include/asm/compat.h
+@@ -185,7 +185,6 @@ typedef struct compat_siginfo {
+ } compat_siginfo_t;
+ #define COMPAT_OFF_T_MAX      0x7fffffff
+-#define COMPAT_LOFF_T_MAX     0x7fffffffffffffffL
+ /*
+  * A pointer passed in from user mode. This should not
+--- a/arch/s390/include/asm/compat.h
++++ b/arch/s390/include/asm/compat.h
+@@ -263,7 +263,6 @@ typedef struct compat_siginfo {
+ #define si_overrun    _sifields._timer._overrun
+ #define COMPAT_OFF_T_MAX      0x7fffffff
+-#define COMPAT_LOFF_T_MAX     0x7fffffffffffffffL
+ /*
+  * A pointer passed in from user mode. This should not
+--- a/arch/sparc/include/asm/compat.h
++++ b/arch/sparc/include/asm/compat.h
+@@ -209,7 +209,6 @@ typedef struct compat_siginfo {
+ } compat_siginfo_t;
+ #define COMPAT_OFF_T_MAX      0x7fffffff
+-#define COMPAT_LOFF_T_MAX     0x7fffffffffffffffL
+ /*
+  * A pointer passed in from user mode. This should not
+--- a/arch/tile/include/asm/compat.h
++++ b/arch/tile/include/asm/compat.h
+@@ -173,7 +173,6 @@ typedef struct compat_siginfo {
+ } compat_siginfo_t;
+ #define COMPAT_OFF_T_MAX      0x7fffffff
+-#define COMPAT_LOFF_T_MAX     0x7fffffffffffffffL
+ struct compat_ipc64_perm {
+       compat_key_t key;
+--- a/arch/x86/include/asm/compat.h
++++ b/arch/x86/include/asm/compat.h
+@@ -209,7 +209,6 @@ typedef struct compat_siginfo {
+ } compat_siginfo_t;
+ #define COMPAT_OFF_T_MAX      0x7fffffff
+-#define COMPAT_LOFF_T_MAX     0x7fffffffffffffffL
+ struct compat_ipc64_perm {
+       compat_key_t key;
+--- a/fs/fcntl.c
++++ b/fs/fcntl.c
+@@ -563,6 +563,9 @@ static int put_compat_flock64(const stru
+ {
+       struct compat_flock64 fl;
++      BUILD_BUG_ON(sizeof(kfl->l_start) > sizeof(ufl->l_start));
++      BUILD_BUG_ON(sizeof(kfl->l_len) > sizeof(ufl->l_len));
++
+       memset(&fl, 0, sizeof(struct compat_flock64));
+       copy_flock_fields(&fl, kfl);
+       if (copy_to_user(ufl, &fl, sizeof(struct compat_flock64)))
+@@ -641,12 +644,8 @@ COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned
+               if (err)
+                       break;
+               err = fcntl_getlk(f.file, convert_fcntl_cmd(cmd), &flock);
+-              if (err)
+-                      break;
+-              err = fixup_compat_flock(&flock);
+-              if (err)
+-                      return err;
+-              err = put_compat_flock64(&flock, compat_ptr(arg));
++              if (!err)
++                      err = put_compat_flock64(&flock, compat_ptr(arg));
+               break;
+       case F_SETLK:
+       case F_SETLKW:
diff --git a/queue-4.14/ipmi-stop-timers-before-cleaning-up-the-module.patch b/queue-4.14/ipmi-stop-timers-before-cleaning-up-the-module.patch
new file mode 100644 (file)
index 0000000..155933a
--- /dev/null
@@ -0,0 +1,256 @@
+From 4f7f5551a760eb0124267be65763008169db7087 Mon Sep 17 00:00:00 2001
+From: Masamitsu Yamazaki <m-yamazaki@ah.jp.nec.com>
+Date: Wed, 15 Nov 2017 07:33:14 +0000
+Subject: ipmi: Stop timers before cleaning up the module
+
+From: Masamitsu Yamazaki <m-yamazaki@ah.jp.nec.com>
+
+commit 4f7f5551a760eb0124267be65763008169db7087 upstream.
+
+System may crash after unloading ipmi_si.ko module
+because a timer may remain and fire after the module cleaned up resources.
+
+cleanup_one_si() contains the following processing.
+
+        /*
+         * Make sure that interrupts, the timer and the thread are
+         * stopped and will not run again.
+         */
+        if (to_clean->irq_cleanup)
+                to_clean->irq_cleanup(to_clean);
+        wait_for_timer_and_thread(to_clean);
+
+        /*
+         * Timeouts are stopped, now make sure the interrupts are off
+         * in the BMC.  Note that timers and CPU interrupts are off,
+         * so no need for locks.
+         */
+        while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
+                poll(to_clean);
+                schedule_timeout_uninterruptible(1);
+        }
+
+si_state changes as following in the while loop calling poll(to_clean).
+
+  SI_GETTING_MESSAGES
+    => SI_CHECKING_ENABLES
+     => SI_SETTING_ENABLES
+      => SI_GETTING_EVENTS
+       => SI_NORMAL
+
+As written in the code comments above,
+timers are expected to stop before the polling loop and not to run again.
+But the timer is set again in the following process
+when si_state becomes SI_SETTING_ENABLES.
+
+  => poll
+     => smi_event_handler
+       => handle_transaction_done
+          // smi_info->si_state == SI_SETTING_ENABLES
+         => start_getting_events
+           => start_new_msg
+            => smi_mod_timer
+              => mod_timer
+
+As a result, before the timer set in start_new_msg() expires,
+the polling loop may see si_state becoming SI_NORMAL
+and the module clean-up finishes.
+
+For example, hard LOCKUP and panic occurred as following.
+smi_timeout was called after smi_event_handler,
+kcs_event and hangs at port_inb()
+trying to access I/O port after release.
+
+    [exception RIP: port_inb+19]
+    RIP: ffffffffc0473053  RSP: ffff88069fdc3d80  RFLAGS: 00000006
+    RAX: ffff8806800f8e00  RBX: ffff880682bd9400  RCX: 0000000000000000
+    RDX: 0000000000000ca3  RSI: 0000000000000ca3  RDI: ffff8806800f8e40
+    RBP: ffff88069fdc3d80   R8: ffffffff81d86dfc   R9: ffffffff81e36426
+    R10: 00000000000509f0  R11: 0000000000100000  R12: 0000000000]:000000
+    R13: 0000000000000000  R14: 0000000000000246  R15: ffff8806800f8e00
+    ORIG_RAX: ffffffffffffffff  CS: 0010  SS: 0000
+ --- <NMI exception stack> ---
+
+To fix the problem I defined a flag, timer_can_start,
+as member of struct smi_info.
+The flag is enabled immediately after initializing the timer
+and disabled immediately before waiting for timer deletion.
+
+Fixes: 0cfec916e86d ("ipmi: Start the timer and thread on internal msgs")
+Signed-off-by: Yamazaki Masamitsu <m-yamazaki@ah.jp.nec.com>
+[Some fairly major changes went into the IPMI driver in 4.15, so this
+ required a backport as the code had changed and moved to a different
+ file.]
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_si_intf.c |   44 ++++++++++++++++++++-------------------
+ 1 file changed, 23 insertions(+), 21 deletions(-)
+
+--- a/drivers/char/ipmi/ipmi_si_intf.c
++++ b/drivers/char/ipmi/ipmi_si_intf.c
+@@ -242,6 +242,9 @@ struct smi_info {
+       /* The timer for this si. */
+       struct timer_list   si_timer;
++      /* This flag is set, if the timer can be set */
++      bool                timer_can_start;
++
+       /* This flag is set, if the timer is running (timer_pending() isn't enough) */
+       bool                timer_running;
+@@ -417,6 +420,8 @@ out:
+ static void smi_mod_timer(struct smi_info *smi_info, unsigned long new_val)
+ {
++      if (!smi_info->timer_can_start)
++              return;
+       smi_info->last_timeout_jiffies = jiffies;
+       mod_timer(&smi_info->si_timer, new_val);
+       smi_info->timer_running = true;
+@@ -436,21 +441,18 @@ static void start_new_msg(struct smi_inf
+       smi_info->handlers->start_transaction(smi_info->si_sm, msg, size);
+ }
+-static void start_check_enables(struct smi_info *smi_info, bool start_timer)
++static void start_check_enables(struct smi_info *smi_info)
+ {
+       unsigned char msg[2];
+       msg[0] = (IPMI_NETFN_APP_REQUEST << 2);
+       msg[1] = IPMI_GET_BMC_GLOBAL_ENABLES_CMD;
+-      if (start_timer)
+-              start_new_msg(smi_info, msg, 2);
+-      else
+-              smi_info->handlers->start_transaction(smi_info->si_sm, msg, 2);
++      start_new_msg(smi_info, msg, 2);
+       smi_info->si_state = SI_CHECKING_ENABLES;
+ }
+-static void start_clear_flags(struct smi_info *smi_info, bool start_timer)
++static void start_clear_flags(struct smi_info *smi_info)
+ {
+       unsigned char msg[3];
+@@ -459,10 +461,7 @@ static void start_clear_flags(struct smi
+       msg[1] = IPMI_CLEAR_MSG_FLAGS_CMD;
+       msg[2] = WDT_PRE_TIMEOUT_INT;
+-      if (start_timer)
+-              start_new_msg(smi_info, msg, 3);
+-      else
+-              smi_info->handlers->start_transaction(smi_info->si_sm, msg, 3);
++      start_new_msg(smi_info, msg, 3);
+       smi_info->si_state = SI_CLEARING_FLAGS;
+ }
+@@ -497,11 +496,11 @@ static void start_getting_events(struct
+  * Note that we cannot just use disable_irq(), since the interrupt may
+  * be shared.
+  */
+-static inline bool disable_si_irq(struct smi_info *smi_info, bool start_timer)
++static inline bool disable_si_irq(struct smi_info *smi_info)
+ {
+       if ((smi_info->irq) && (!smi_info->interrupt_disabled)) {
+               smi_info->interrupt_disabled = true;
+-              start_check_enables(smi_info, start_timer);
++              start_check_enables(smi_info);
+               return true;
+       }
+       return false;
+@@ -511,7 +510,7 @@ static inline bool enable_si_irq(struct
+ {
+       if ((smi_info->irq) && (smi_info->interrupt_disabled)) {
+               smi_info->interrupt_disabled = false;
+-              start_check_enables(smi_info, true);
++              start_check_enables(smi_info);
+               return true;
+       }
+       return false;
+@@ -529,7 +528,7 @@ static struct ipmi_smi_msg *alloc_msg_ha
+       msg = ipmi_alloc_smi_msg();
+       if (!msg) {
+-              if (!disable_si_irq(smi_info, true))
++              if (!disable_si_irq(smi_info))
+                       smi_info->si_state = SI_NORMAL;
+       } else if (enable_si_irq(smi_info)) {
+               ipmi_free_smi_msg(msg);
+@@ -545,7 +544,7 @@ retry:
+               /* Watchdog pre-timeout */
+               smi_inc_stat(smi_info, watchdog_pretimeouts);
+-              start_clear_flags(smi_info, true);
++              start_clear_flags(smi_info);
+               smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT;
+               if (smi_info->intf)
+                       ipmi_smi_watchdog_pretimeout(smi_info->intf);
+@@ -928,7 +927,7 @@ restart:
+                * disable and messages disabled.
+                */
+               if (smi_info->supports_event_msg_buff || smi_info->irq) {
+-                      start_check_enables(smi_info, true);
++                      start_check_enables(smi_info);
+               } else {
+                       smi_info->curr_msg = alloc_msg_handle_irq(smi_info);
+                       if (!smi_info->curr_msg)
+@@ -1235,6 +1234,7 @@ static int smi_start_processing(void
+       /* Set up the timer that drives the interface. */
+       setup_timer(&new_smi->si_timer, smi_timeout, (long)new_smi);
++      new_smi->timer_can_start = true;
+       smi_mod_timer(new_smi, jiffies + SI_TIMEOUT_JIFFIES);
+       /* Try to claim any interrupts. */
+@@ -3416,10 +3416,12 @@ static void check_for_broken_irqs(struct
+       check_set_rcv_irq(smi_info);
+ }
+-static inline void wait_for_timer_and_thread(struct smi_info *smi_info)
++static inline void stop_timer_and_thread(struct smi_info *smi_info)
+ {
+       if (smi_info->thread != NULL)
+               kthread_stop(smi_info->thread);
++
++      smi_info->timer_can_start = false;
+       if (smi_info->timer_running)
+               del_timer_sync(&smi_info->si_timer);
+ }
+@@ -3605,7 +3607,7 @@ static int try_smi_init(struct smi_info
+        * Start clearing the flags before we enable interrupts or the
+        * timer to avoid racing with the timer.
+        */
+-      start_clear_flags(new_smi, false);
++      start_clear_flags(new_smi);
+       /*
+        * IRQ is defined to be set when non-zero.  req_events will
+@@ -3674,7 +3676,7 @@ static int try_smi_init(struct smi_info
+       return 0;
+ out_err_stop_timer:
+-      wait_for_timer_and_thread(new_smi);
++      stop_timer_and_thread(new_smi);
+ out_err:
+       new_smi->interrupt_disabled = true;
+@@ -3866,7 +3868,7 @@ static void cleanup_one_si(struct smi_in
+        */
+       if (to_clean->irq_cleanup)
+               to_clean->irq_cleanup(to_clean);
+-      wait_for_timer_and_thread(to_clean);
++      stop_timer_and_thread(to_clean);
+       /*
+        * Timeouts are stopped, now make sure the interrupts are off
+@@ -3878,7 +3880,7 @@ static void cleanup_one_si(struct smi_in
+               schedule_timeout_uninterruptible(1);
+       }
+       if (to_clean->handlers)
+-              disable_si_irq(to_clean, false);
++              disable_si_irq(to_clean);
+       while (to_clean->curr_msg || (to_clean->si_state != SI_NORMAL)) {
+               poll(to_clean);
+               schedule_timeout_uninterruptible(1);
index 5d0f32a38c24a3b413067bc08cd94fe683455ce2..c370d6dd6ed74dcbc3185b45a09d348f9ee6edd5 100644 (file)
@@ -31,3 +31,6 @@ net-accept-ufo-datagrams-from-tuntap-and-packet.patch
 net-openvswitch-datapath-fix-data-type-in-queue_gso_packets.patch
 cls_bpf-don-t-decrement-net-s-refcount-when-offload-fails.patch
 sctp-use-right-member-as-the-param-of-list_for_each_entry.patch
+ipmi-stop-timers-before-cleaning-up-the-module.patch
+usb-gadget-ffs-forbid-usb_ep_alloc_request-from-sleeping.patch
+fcntl-don-t-cap-l_start-and-l_end-values-for-f_getlk64-in-compat-syscall.patch
diff --git a/queue-4.14/usb-gadget-ffs-forbid-usb_ep_alloc_request-from-sleeping.patch b/queue-4.14/usb-gadget-ffs-forbid-usb_ep_alloc_request-from-sleeping.patch
new file mode 100644 (file)
index 0000000..874528c
--- /dev/null
@@ -0,0 +1,64 @@
+From 30bf90ccdec1da9c8198b161ecbff39ce4e5a9ba Mon Sep 17 00:00:00 2001
+From: Vincent Pelletier <plr.vincent@gmail.com>
+Date: Sun, 26 Nov 2017 06:52:53 +0000
+Subject: usb: gadget: ffs: Forbid usb_ep_alloc_request from sleeping
+
+From: Vincent Pelletier <plr.vincent@gmail.com>
+
+commit 30bf90ccdec1da9c8198b161ecbff39ce4e5a9ba upstream.
+
+Found using DEBUG_ATOMIC_SLEEP while submitting an AIO read operation:
+
+[  100.853642] BUG: sleeping function called from invalid context at mm/slab.h:421
+[  100.861148] in_atomic(): 1, irqs_disabled(): 1, pid: 1880, name: python
+[  100.867954] 2 locks held by python/1880:
+[  100.867961]  #0:  (&epfile->mutex){....}, at: [<f8188627>] ffs_mutex_lock+0x27/0x30 [usb_f_fs]
+[  100.868020]  #1:  (&(&ffs->eps_lock)->rlock){....}, at: [<f818ad4b>] ffs_epfile_io.isra.17+0x24b/0x590 [usb_f_fs]
+[  100.868076] CPU: 1 PID: 1880 Comm: python Not tainted 4.14.0-edison+ #118
+[  100.868085] Hardware name: Intel Corporation Merrifield/BODEGA BAY, BIOS 542 2015.01.21:18.19.48
+[  100.868093] Call Trace:
+[  100.868122]  dump_stack+0x47/0x62
+[  100.868156]  ___might_sleep+0xfd/0x110
+[  100.868182]  __might_sleep+0x68/0x70
+[  100.868217]  kmem_cache_alloc_trace+0x4b/0x200
+[  100.868248]  ? dwc3_gadget_ep_alloc_request+0x24/0xe0 [dwc3]
+[  100.868302]  dwc3_gadget_ep_alloc_request+0x24/0xe0 [dwc3]
+[  100.868343]  usb_ep_alloc_request+0x16/0xc0 [udc_core]
+[  100.868386]  ffs_epfile_io.isra.17+0x444/0x590 [usb_f_fs]
+[  100.868424]  ? _raw_spin_unlock_irqrestore+0x27/0x40
+[  100.868457]  ? kiocb_set_cancel_fn+0x57/0x60
+[  100.868477]  ? ffs_ep0_poll+0xc0/0xc0 [usb_f_fs]
+[  100.868512]  ffs_epfile_read_iter+0xfe/0x157 [usb_f_fs]
+[  100.868551]  ? security_file_permission+0x9c/0xd0
+[  100.868587]  ? rw_verify_area+0xac/0x120
+[  100.868633]  aio_read+0x9d/0x100
+[  100.868692]  ? __fget+0xa2/0xd0
+[  100.868727]  ? __might_sleep+0x68/0x70
+[  100.868763]  SyS_io_submit+0x471/0x680
+[  100.868878]  do_int80_syscall_32+0x4e/0xd0
+[  100.868921]  entry_INT80_32+0x2a/0x2a
+[  100.868932] EIP: 0xb7fbb676
+[  100.868941] EFLAGS: 00000292 CPU: 1
+[  100.868951] EAX: ffffffda EBX: b7aa2000 ECX: 00000002 EDX: b7af8368
+[  100.868961] ESI: b7fbb660 EDI: b7aab000 EBP: bfb6c658 ESP: bfb6c638
+[  100.868973]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b
+
+Signed-off-by: Vincent Pelletier <plr.vincent@gmail.com>
+Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/gadget/function/f_fs.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/usb/gadget/function/f_fs.c
++++ b/drivers/usb/gadget/function/f_fs.c
+@@ -1016,7 +1016,7 @@ static ssize_t ffs_epfile_io(struct file
+               else
+                       ret = ep->status;
+               goto error_mutex;
+-      } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_KERNEL))) {
++      } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) {
+               ret = -ENOMEM;
+       } else {
+               req->buf      = data;