]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Jun 2017 06:15:43 +0000 (08:15 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Jun 2017 06:15:43 +0000 (08:15 +0200)
added patches:
autofs-sanity-check-status-reported-with-autofs_dev_ioctl_fail.patch
cifs-improve-readdir-verbosity.patch
fs-exec.c-account-for-argv-envp-pointers.patch
hid-add-quirk-for-dell-pixart-oem-mouse.patch
kvm-ppc-book3s-hv-preserve-userspace-htm-state-properly.patch
lib-cmdline.c-fix-get_options-overflow-while-parsing-ranges.patch
signal-only-reschedule-timers-on-signals-timers-have-sent.patch

queue-4.4/autofs-sanity-check-status-reported-with-autofs_dev_ioctl_fail.patch [new file with mode: 0644]
queue-4.4/cifs-improve-readdir-verbosity.patch [new file with mode: 0644]
queue-4.4/fs-exec.c-account-for-argv-envp-pointers.patch [new file with mode: 0644]
queue-4.4/hid-add-quirk-for-dell-pixart-oem-mouse.patch [new file with mode: 0644]
queue-4.4/kvm-ppc-book3s-hv-preserve-userspace-htm-state-properly.patch [new file with mode: 0644]
queue-4.4/lib-cmdline.c-fix-get_options-overflow-while-parsing-ranges.patch [new file with mode: 0644]
queue-4.4/signal-only-reschedule-timers-on-signals-timers-have-sent.patch [new file with mode: 0644]

diff --git a/queue-4.4/autofs-sanity-check-status-reported-with-autofs_dev_ioctl_fail.patch b/queue-4.4/autofs-sanity-check-status-reported-with-autofs_dev_ioctl_fail.patch
new file mode 100644 (file)
index 0000000..2d5f930
--- /dev/null
@@ -0,0 +1,43 @@
+From 9fa4eb8e490a28de40964b1b0e583d8db4c7e57c Mon Sep 17 00:00:00 2001
+From: NeilBrown <neilb@suse.com>
+Date: Fri, 23 Jun 2017 15:08:43 -0700
+Subject: autofs: sanity check status reported with AUTOFS_DEV_IOCTL_FAIL
+
+From: NeilBrown <neilb@suse.com>
+
+commit 9fa4eb8e490a28de40964b1b0e583d8db4c7e57c upstream.
+
+If a positive status is passed with the AUTOFS_DEV_IOCTL_FAIL ioctl,
+autofs4_d_automount() will return
+
+   ERR_PTR(status)
+
+with that status to follow_automount(), which will then dereference an
+invalid pointer.
+
+So treat a positive status the same as zero, and map to ENOENT.
+
+See comment in systemd src/core/automount.c::automount_send_ready().
+
+Link: http://lkml.kernel.org/r/871sqwczx5.fsf@notabene.neil.brown.name
+Signed-off-by: NeilBrown <neilb@suse.com>
+Cc: Ian Kent <raven@themaw.net>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/autofs4/dev-ioctl.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/autofs4/dev-ioctl.c
++++ b/fs/autofs4/dev-ioctl.c
+@@ -331,7 +331,7 @@ static int autofs_dev_ioctl_fail(struct
+       int status;
+       token = (autofs_wqt_t) param->fail.token;
+-      status = param->fail.status ? param->fail.status : -ENOENT;
++      status = param->fail.status < 0 ? param->fail.status : -ENOENT;
+       return autofs4_wait_release(sbi, token, status);
+ }
diff --git a/queue-4.4/cifs-improve-readdir-verbosity.patch b/queue-4.4/cifs-improve-readdir-verbosity.patch
new file mode 100644 (file)
index 0000000..68f7cf1
--- /dev/null
@@ -0,0 +1,60 @@
+From dcd87838c06f05ab7650b249ebf0d5b57ae63e1e Mon Sep 17 00:00:00 2001
+From: Pavel Shilovsky <pshilov@microsoft.com>
+Date: Tue, 6 Jun 2017 16:58:58 -0700
+Subject: CIFS: Improve readdir verbosity
+
+From: Pavel Shilovsky <pshilov@microsoft.com>
+
+commit dcd87838c06f05ab7650b249ebf0d5b57ae63e1e upstream.
+
+Downgrade the loglevel for SMB2 to prevent filling the log
+with messages if e.g. readdir was interrupted. Also make SMB2
+and SMB1 codepaths do the same logging during readdir.
+
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <smfrench@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb1ops.c |    9 +++++++--
+ fs/cifs/smb2ops.c |    4 ++--
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+--- a/fs/cifs/smb1ops.c
++++ b/fs/cifs/smb1ops.c
+@@ -849,8 +849,13 @@ cifs_query_dir_first(const unsigned int
+                    struct cifs_fid *fid, __u16 search_flags,
+                    struct cifs_search_info *srch_inf)
+ {
+-      return CIFSFindFirst(xid, tcon, path, cifs_sb,
+-                           &fid->netfid, search_flags, srch_inf, true);
++      int rc;
++
++      rc = CIFSFindFirst(xid, tcon, path, cifs_sb,
++                         &fid->netfid, search_flags, srch_inf, true);
++      if (rc)
++              cifs_dbg(FYI, "find first failed=%d\n", rc);
++      return rc;
+ }
+ static int
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -909,7 +909,7 @@ smb2_query_dir_first(const unsigned int
+       rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL);
+       kfree(utf16_path);
+       if (rc) {
+-              cifs_dbg(VFS, "open dir failed\n");
++              cifs_dbg(FYI, "open dir failed rc=%d\n", rc);
+               return rc;
+       }
+@@ -919,7 +919,7 @@ smb2_query_dir_first(const unsigned int
+       rc = SMB2_query_directory(xid, tcon, fid->persistent_fid,
+                                 fid->volatile_fid, 0, srch_inf);
+       if (rc) {
+-              cifs_dbg(VFS, "query directory failed\n");
++              cifs_dbg(FYI, "query directory failed rc=%d\n", rc);
+               SMB2_close(xid, tcon, fid->persistent_fid, fid->volatile_fid);
+       }
+       return rc;
diff --git a/queue-4.4/fs-exec.c-account-for-argv-envp-pointers.patch b/queue-4.4/fs-exec.c-account-for-argv-envp-pointers.patch
new file mode 100644 (file)
index 0000000..81e92d6
--- /dev/null
@@ -0,0 +1,89 @@
+From 98da7d08850fb8bdeb395d6368ed15753304aa0c Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Fri, 23 Jun 2017 15:08:57 -0700
+Subject: fs/exec.c: account for argv/envp pointers
+
+From: Kees Cook <keescook@chromium.org>
+
+commit 98da7d08850fb8bdeb395d6368ed15753304aa0c upstream.
+
+When limiting the argv/envp strings during exec to 1/4 of the stack limit,
+the storage of the pointers to the strings was not included.  This means
+that an exec with huge numbers of tiny strings could eat 1/4 of the stack
+limit in strings and then additional space would be later used by the
+pointers to the strings.
+
+For example, on 32-bit with a 8MB stack rlimit, an exec with 1677721
+single-byte strings would consume less than 2MB of stack, the max (8MB /
+4) amount allowed, but the pointers to the strings would consume the
+remaining additional stack space (1677721 * 4 == 6710884).
+
+The result (1677721 + 6710884 == 8388605) would exhaust stack space
+entirely.  Controlling this stack exhaustion could result in
+pathological behavior in setuid binaries (CVE-2017-1000365).
+
+[akpm@linux-foundation.org: additional commenting from Kees]
+Fixes: b6a2fea39318 ("mm: variable length argument support")
+Link: http://lkml.kernel.org/r/20170622001720.GA32173@beast
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Acked-by: Rik van Riel <riel@redhat.com>
+Acked-by: Michal Hocko <mhocko@suse.com>
+Cc: Alexander Viro <viro@zeniv.linux.org.uk>
+Cc: Qualys Security Advisory <qsa@qualys.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/exec.c |   28 ++++++++++++++++++++++++----
+ 1 file changed, 24 insertions(+), 4 deletions(-)
+
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -206,8 +206,26 @@ static struct page *get_arg_page(struct
+       if (write) {
+               unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start;
++              unsigned long ptr_size;
+               struct rlimit *rlim;
++              /*
++               * Since the stack will hold pointers to the strings, we
++               * must account for them as well.
++               *
++               * The size calculation is the entire vma while each arg page is
++               * built, so each time we get here it's calculating how far it
++               * is currently (rather than each call being just the newly
++               * added size from the arg page).  As a result, we need to
++               * always add the entire size of the pointers, so that on the
++               * last call to get_arg_page() we'll actually have the entire
++               * correct size.
++               */
++              ptr_size = (bprm->argc + bprm->envc) * sizeof(void *);
++              if (ptr_size > ULONG_MAX - size)
++                      goto fail;
++              size += ptr_size;
++
+               acct_arg_size(bprm, size / PAGE_SIZE);
+               /*
+@@ -225,13 +243,15 @@ static struct page *get_arg_page(struct
+                *    to work from.
+                */
+               rlim = current->signal->rlim;
+-              if (size > ACCESS_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4) {
+-                      put_page(page);
+-                      return NULL;
+-              }
++              if (size > READ_ONCE(rlim[RLIMIT_STACK].rlim_cur) / 4)
++                      goto fail;
+       }
+       return page;
++
++fail:
++      put_page(page);
++      return NULL;
+ }
+ static void put_arg_page(struct page *page)
diff --git a/queue-4.4/hid-add-quirk-for-dell-pixart-oem-mouse.patch b/queue-4.4/hid-add-quirk-for-dell-pixart-oem-mouse.patch
new file mode 100644 (file)
index 0000000..bbb301a
--- /dev/null
@@ -0,0 +1,43 @@
+From 3db28271f0feae129262d30e41384a7c4c767987 Mon Sep 17 00:00:00 2001
+From: Sebastian Parschauer <sparschauer@suse.de>
+Date: Tue, 6 Jun 2017 13:53:13 +0200
+Subject: HID: Add quirk for Dell PIXART OEM mouse
+
+From: Sebastian Parschauer <sparschauer@suse.de>
+
+commit 3db28271f0feae129262d30e41384a7c4c767987 upstream.
+
+This mouse is also known under other IDs. It needs the quirk
+ALWAYS_POLL or will disconnect in runlevel 1 or 3.
+
+Signed-off-by: Sebastian Parschauer <sparschauer@suse.de>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-ids.h           |    3 +++
+ drivers/hid/usbhid/hid-quirks.c |    1 +
+ 2 files changed, 4 insertions(+)
+
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -285,6 +285,9 @@
+ #define USB_VENDOR_ID_DEALEXTREAME    0x10c5
+ #define USB_DEVICE_ID_DEALEXTREAME_RADIO_SI4701       0x819a
++#define USB_VENDOR_ID_DELL                            0x413c
++#define USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE   0x301a
++
+ #define USB_VENDOR_ID_DELORME         0x1163
+ #define USB_DEVICE_ID_DELORME_EARTHMATE       0x0100
+ #define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
+--- a/drivers/hid/usbhid/hid-quirks.c
++++ b/drivers/hid/usbhid/hid-quirks.c
+@@ -72,6 +72,7 @@ static const struct hid_blacklist {
+       { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_CREATIVE_SB_OMNI_SURROUND_51, HID_QUIRK_NOGET },
++      { USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_PIXART_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL },
+       { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_DRAGONRISE, USB_DEVICE_ID_DRAGONRISE_WIIU, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_ELAN, HID_ANY_ID, HID_QUIRK_ALWAYS_POLL },
diff --git a/queue-4.4/kvm-ppc-book3s-hv-preserve-userspace-htm-state-properly.patch b/queue-4.4/kvm-ppc-book3s-hv-preserve-userspace-htm-state-properly.patch
new file mode 100644 (file)
index 0000000..77d7d2e
--- /dev/null
@@ -0,0 +1,63 @@
+From 46a704f8409f79fd66567ad3f8a7304830a84293 Mon Sep 17 00:00:00 2001
+From: Paul Mackerras <paulus@ozlabs.org>
+Date: Thu, 15 Jun 2017 16:10:27 +1000
+Subject: KVM: PPC: Book3S HV: Preserve userspace HTM state properly
+
+From: Paul Mackerras <paulus@ozlabs.org>
+
+commit 46a704f8409f79fd66567ad3f8a7304830a84293 upstream.
+
+If userspace attempts to call the KVM_RUN ioctl when it has hardware
+transactional memory (HTM) enabled, the values that it has put in the
+HTM-related SPRs TFHAR, TFIAR and TEXASR will get overwritten by
+guest values.  To fix this, we detect this condition and save those
+SPR values in the thread struct, and disable HTM for the task.  If
+userspace goes to access those SPRs or the HTM facility in future,
+a TM-unavailable interrupt will occur and the handler will reload
+those SPRs and re-enable HTM.
+
+If userspace has started a transaction and suspended it, we would
+currently lose the transactional state in the guest entry path and
+would almost certainly get a "TM Bad Thing" interrupt, which would
+cause the host to crash.  To avoid this, we detect this case and
+return from the KVM_RUN ioctl with an EINVAL error, with the KVM
+exit reason set to KVM_EXIT_FAIL_ENTRY.
+
+Fixes: b005255e12a3 ("KVM: PPC: Book3S HV: Context-switch new POWER8 SPRs", 2014-01-08)
+Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/kvm/book3s_hv.c |   21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+
+--- a/arch/powerpc/kvm/book3s_hv.c
++++ b/arch/powerpc/kvm/book3s_hv.c
+@@ -2693,6 +2693,27 @@ static int kvmppc_vcpu_run_hv(struct kvm
+               return -EINVAL;
+       }
++      /*
++       * Don't allow entry with a suspended transaction, because
++       * the guest entry/exit code will lose it.
++       * If the guest has TM enabled, save away their TM-related SPRs
++       * (they will get restored by the TM unavailable interrupt).
++       */
++#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
++      if (cpu_has_feature(CPU_FTR_TM) && current->thread.regs &&
++          (current->thread.regs->msr & MSR_TM)) {
++              if (MSR_TM_ACTIVE(current->thread.regs->msr)) {
++                      run->exit_reason = KVM_EXIT_FAIL_ENTRY;
++                      run->fail_entry.hardware_entry_failure_reason = 0;
++                      return -EINVAL;
++              }
++              current->thread.tm_tfhar = mfspr(SPRN_TFHAR);
++              current->thread.tm_tfiar = mfspr(SPRN_TFIAR);
++              current->thread.tm_texasr = mfspr(SPRN_TEXASR);
++              current->thread.regs->msr &= ~MSR_TM;
++      }
++#endif
++
+       kvmppc_core_prepare_to_enter(vcpu);
+       /* No need to go into the guest when all we'll do is come back out */
diff --git a/queue-4.4/lib-cmdline.c-fix-get_options-overflow-while-parsing-ranges.patch b/queue-4.4/lib-cmdline.c-fix-get_options-overflow-while-parsing-ranges.patch
new file mode 100644 (file)
index 0000000..c6c8678
--- /dev/null
@@ -0,0 +1,53 @@
+From a91e0f680bcd9e10c253ae8b62462a38bd48f09f Mon Sep 17 00:00:00 2001
+From: Ilya Matveychikov <matvejchikov@gmail.com>
+Date: Fri, 23 Jun 2017 15:08:49 -0700
+Subject: lib/cmdline.c: fix get_options() overflow while parsing ranges
+
+From: Ilya Matveychikov <matvejchikov@gmail.com>
+
+commit a91e0f680bcd9e10c253ae8b62462a38bd48f09f upstream.
+
+When using get_options() it's possible to specify a range of numbers,
+like 1-100500.  The problem is that it doesn't track array size while
+calling internally to get_range() which iterates over the range and
+fills the memory with numbers.
+
+Link: http://lkml.kernel.org/r/2613C75C-B04D-4BFF-82A6-12F97BA0F620@gmail.com
+Signed-off-by: Ilya V. Matveychikov <matvejchikov@gmail.com>
+Cc: Jonathan Corbet <corbet@lwn.net>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ lib/cmdline.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/lib/cmdline.c
++++ b/lib/cmdline.c
+@@ -22,14 +22,14 @@
+  *    the values[M, M+1, ..., N] into the ints array in get_options.
+  */
+-static int get_range(char **str, int *pint)
++static int get_range(char **str, int *pint, int n)
+ {
+       int x, inc_counter, upper_range;
+       (*str)++;
+       upper_range = simple_strtol((*str), NULL, 0);
+       inc_counter = upper_range - *pint;
+-      for (x = *pint; x < upper_range; x++)
++      for (x = *pint; n && x < upper_range; x++, n--)
+               *pint++ = x;
+       return inc_counter;
+ }
+@@ -96,7 +96,7 @@ char *get_options(const char *str, int n
+                       break;
+               if (res == 3) {
+                       int range_nums;
+-                      range_nums = get_range((char **)&str, ints + i);
++                      range_nums = get_range((char **)&str, ints + i, nints - i);
+                       if (range_nums < 0)
+                               break;
+                       /*
diff --git a/queue-4.4/signal-only-reschedule-timers-on-signals-timers-have-sent.patch b/queue-4.4/signal-only-reschedule-timers-on-signals-timers-have-sent.patch
new file mode 100644 (file)
index 0000000..928fe85
--- /dev/null
@@ -0,0 +1,152 @@
+From 57db7e4a2d92c2d3dfbca4ef8057849b2682436b Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Tue, 13 Jun 2017 04:31:16 -0500
+Subject: signal: Only reschedule timers on signals timers have sent
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+commit 57db7e4a2d92c2d3dfbca4ef8057849b2682436b upstream.
+
+Thomas Gleixner  wrote:
+> The CRIU support added a 'feature' which allows a user space task to send
+> arbitrary (kernel) signals to itself. The changelog says:
+>
+>   The kernel prevents sending of siginfo with positive si_code, because
+>   these codes are reserved for kernel.  I think we can allow a task to
+>   send such a siginfo to itself.  This operation should not be dangerous.
+>
+> Quite contrary to that claim, it turns out that it is outright dangerous
+> for signals with info->si_code == SI_TIMER. The following code sequence in
+> a user space task allows to crash the kernel:
+>
+>    id = timer_create(CLOCK_XXX, ..... signo = SIGX);
+>    timer_set(id, ....);
+>    info->si_signo = SIGX;
+>    info->si_code = SI_TIMER:
+>    info->_sifields._timer._tid = id;
+>    info->_sifields._timer._sys_private = 2;
+>    rt_[tg]sigqueueinfo(..., SIGX, info);
+>    sigemptyset(&sigset);
+>    sigaddset(&sigset, SIGX);
+>    rt_sigtimedwait(sigset, info);
+>
+> For timers based on CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID this
+> results in a kernel crash because sigwait() dequeues the signal and the
+> dequeue code observes:
+>
+>   info->si_code == SI_TIMER && info->_sifields._timer._sys_private != 0
+>
+> which triggers the following callchain:
+>
+>  do_schedule_next_timer() -> posix_cpu_timer_schedule() -> arm_timer()
+>
+> arm_timer() executes a list_add() on the timer, which is already armed via
+> the timer_set() syscall. That's a double list add which corrupts the posix
+> cpu timer list. As a consequence the kernel crashes on the next operation
+> touching the posix cpu timer list.
+>
+> Posix clocks which are internally implemented based on hrtimers are not
+> affected by this because hrtimer_start() can handle already armed timers
+> nicely, but it's a reliable way to trigger the WARN_ON() in
+> hrtimer_forward(), which complains about calling that function on an
+> already armed timer.
+
+This problem has existed since the posix timer code was merged into
+2.5.63. A few releases earlier in 2.5.60 ptrace gained the ability to
+inject not just a signal (which linux has supported since 1.0) but the
+full siginfo of a signal.
+
+The core problem is that the code will reschedule in response to
+signals getting dequeued not just for signals the timers sent but
+for other signals that happen to a si_code of SI_TIMER.
+
+Avoid this confusion by testing to see if the queued signal was
+preallocated as all timer signals are preallocated, and so far
+only the timer code preallocates signals.
+
+Move the check for if a timer needs to be rescheduled up into
+collect_signal where the preallocation check must be performed,
+and pass the result back to dequeue_signal where the code reschedules
+timers.   This makes it clear why the code cares about preallocated
+timers.
+
+Reported-by: Thomas Gleixner <tglx@linutronix.de>
+History Tree: https://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
+Reference: 66dd34ad31e5 ("signal: allow to send any siginfo to itself")
+Reference: 1669ce53e2ff ("Add PTRACE_GETSIGINFO and PTRACE_SETSIGINFO")
+Fixes: db8b50ba75f2 ("[PATCH] POSIX clocks & timers")
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/signal.c |   20 ++++++++++++++------
+ 1 file changed, 14 insertions(+), 6 deletions(-)
+
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -503,7 +503,8 @@ int unhandled_signal(struct task_struct
+       return !tsk->ptrace;
+ }
+-static void collect_signal(int sig, struct sigpending *list, siginfo_t *info)
++static void collect_signal(int sig, struct sigpending *list, siginfo_t *info,
++                         bool *resched_timer)
+ {
+       struct sigqueue *q, *first = NULL;
+@@ -525,6 +526,12 @@ static void collect_signal(int sig, stru
+ still_pending:
+               list_del_init(&first->list);
+               copy_siginfo(info, &first->info);
++
++              *resched_timer =
++                      (first->flags & SIGQUEUE_PREALLOC) &&
++                      (info->si_code == SI_TIMER) &&
++                      (info->si_sys_private);
++
+               __sigqueue_free(first);
+       } else {
+               /*
+@@ -541,12 +548,12 @@ still_pending:
+ }
+ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
+-                      siginfo_t *info)
++                      siginfo_t *info, bool *resched_timer)
+ {
+       int sig = next_signal(pending, mask);
+       if (sig)
+-              collect_signal(sig, pending, info);
++              collect_signal(sig, pending, info, resched_timer);
+       return sig;
+ }
+@@ -558,15 +565,16 @@ static int __dequeue_signal(struct sigpe
+  */
+ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+ {
++      bool resched_timer = false;
+       int signr;
+       /* We only dequeue private signals from ourselves, we don't let
+        * signalfd steal them
+        */
+-      signr = __dequeue_signal(&tsk->pending, mask, info);
++      signr = __dequeue_signal(&tsk->pending, mask, info, &resched_timer);
+       if (!signr) {
+               signr = __dequeue_signal(&tsk->signal->shared_pending,
+-                                       mask, info);
++                                       mask, info, &resched_timer);
+               /*
+                * itimer signal ?
+                *
+@@ -611,7 +619,7 @@ int dequeue_signal(struct task_struct *t
+                */
+               current->jobctl |= JOBCTL_STOP_DEQUEUED;
+       }
+-      if ((info->si_code & __SI_MASK) == __SI_TIMER && info->si_sys_private) {
++      if (resched_timer) {
+               /*
+                * Release the siglock to ensure proper locking order
+                * of timer locks outside of siglocks.  Note, we leave