]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Dec 2020 08:45:25 +0000 (09:45 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 9 Dec 2020 08:45:25 +0000 (09:45 +0100)
added patches:
cifs-fix-potential-use-after-free-in-cifs_echo_request.patch
powerpc-pseries-pass-msi-affinity-to-irq_create_mapping.patch
tty-fix-session-locking.patch

queue-4.4/cifs-fix-potential-use-after-free-in-cifs_echo_request.patch [new file with mode: 0644]
queue-4.4/powerpc-pseries-pass-msi-affinity-to-irq_create_mapping.patch [new file with mode: 0644]
queue-4.4/series
queue-4.4/tty-fix-session-locking.patch [new file with mode: 0644]

diff --git a/queue-4.4/cifs-fix-potential-use-after-free-in-cifs_echo_request.patch b/queue-4.4/cifs-fix-potential-use-after-free-in-cifs_echo_request.patch
new file mode 100644 (file)
index 0000000..2a5b934
--- /dev/null
@@ -0,0 +1,51 @@
+From 212253367dc7b49ed3fc194ce71b0992eacaecf2 Mon Sep 17 00:00:00 2001
+From: Paulo Alcantara <pc@cjr.nz>
+Date: Sat, 28 Nov 2020 16:54:02 -0300
+Subject: cifs: fix potential use-after-free in cifs_echo_request()
+
+From: Paulo Alcantara <pc@cjr.nz>
+
+commit 212253367dc7b49ed3fc194ce71b0992eacaecf2 upstream.
+
+This patch fixes a potential use-after-free bug in
+cifs_echo_request().
+
+For instance,
+
+  thread 1
+  --------
+  cifs_demultiplex_thread()
+    clean_demultiplex_info()
+      kfree(server)
+
+  thread 2 (workqueue)
+  --------
+  apic_timer_interrupt()
+    smp_apic_timer_interrupt()
+      irq_exit()
+        __do_softirq()
+          run_timer_softirq()
+            call_timer_fn()
+             cifs_echo_request() <- use-after-free in server ptr
+
+Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
+CC: Stable <stable@vger.kernel.org>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/connect.c |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -783,6 +783,8 @@ static void clean_demultiplex_info(struc
+       list_del_init(&server->tcp_ses_list);
+       spin_unlock(&cifs_tcp_ses_lock);
++      cancel_delayed_work_sync(&server->echo);
++
+       spin_lock(&GlobalMid_Lock);
+       server->tcpStatus = CifsExiting;
+       spin_unlock(&GlobalMid_Lock);
diff --git a/queue-4.4/powerpc-pseries-pass-msi-affinity-to-irq_create_mapping.patch b/queue-4.4/powerpc-pseries-pass-msi-affinity-to-irq_create_mapping.patch
new file mode 100644 (file)
index 0000000..8440ef0
--- /dev/null
@@ -0,0 +1,54 @@
+From 9ea69a55b3b9a71cded9726af591949c1138f235 Mon Sep 17 00:00:00 2001
+From: Laurent Vivier <lvivier@redhat.com>
+Date: Thu, 26 Nov 2020 09:28:52 +0100
+Subject: powerpc/pseries: Pass MSI affinity to irq_create_mapping()
+
+From: Laurent Vivier <lvivier@redhat.com>
+
+commit 9ea69a55b3b9a71cded9726af591949c1138f235 upstream.
+
+With virtio multiqueue, normally each queue IRQ is mapped to a CPU.
+
+Commit 0d9f0a52c8b9f ("virtio_scsi: use virtio IRQ affinity") exposed
+an existing shortcoming of the arch code by moving virtio_scsi to
+the automatic IRQ affinity assignment.
+
+The affinity is correctly computed in msi_desc but this is not applied
+to the system IRQs.
+
+It appears the affinity is correctly passed to rtas_setup_msi_irqs() but
+lost at this point and never passed to irq_domain_alloc_descs()
+(see commit 06ee6d571f0e ("genirq: Add affinity hint to irq allocation"))
+because irq_create_mapping() doesn't take an affinity parameter.
+
+Use the new irq_create_mapping_affinity() function, which allows to forward
+the affinity setting from rtas_setup_msi_irqs() to irq_domain_alloc_descs().
+
+With this change, the virtqueues are correctly dispatched between the CPUs
+on pseries.
+
+Fixes: e75eafb9b039 ("genirq/msi: Switch to new irq spreading infrastructure")
+Signed-off-by: Laurent Vivier <lvivier@redhat.com>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Greg Kurz <groug@kaod.org>
+Acked-by: Michael Ellerman <mpe@ellerman.id.au>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20201126082852.1178497-3-lvivier@redhat.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/powerpc/platforms/pseries/msi.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/arch/powerpc/platforms/pseries/msi.c
++++ b/arch/powerpc/platforms/pseries/msi.c
+@@ -469,7 +469,8 @@ again:
+                       return hwirq;
+               }
+-              virq = irq_create_mapping(NULL, hwirq);
++              virq = irq_create_mapping_affinity(NULL, hwirq,
++                                                 entry->affinity);
+               if (virq == NO_IRQ) {
+                       pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq);
index 5e8eeb3cfd9f59b5ea08efb9ca981adfd3f9a2bd..31244b0db4f185d646b83f94456948278e6e73cc 100644 (file)
@@ -22,3 +22,6 @@ usb-serial-option-add-support-for-thales-cinterion-exs82.patch
 tty-fix-pgrp-locking-in-tiocspgrp.patch
 alsa-hda-realtek-add-new-codec-supported-for-alc897.patch
 alsa-hda-generic-add-option-to-enforce-preferred_dacs-pairs.patch
+tty-fix-session-locking.patch
+cifs-fix-potential-use-after-free-in-cifs_echo_request.patch
+powerpc-pseries-pass-msi-affinity-to-irq_create_mapping.patch
diff --git a/queue-4.4/tty-fix-session-locking.patch b/queue-4.4/tty-fix-session-locking.patch
new file mode 100644 (file)
index 0000000..fe83471
--- /dev/null
@@ -0,0 +1,197 @@
+From c8bcd9c5be24fb9e6132e97da5a35e55a83e36b9 Mon Sep 17 00:00:00 2001
+From: Jann Horn <jannh@google.com>
+Date: Thu, 3 Dec 2020 02:25:05 +0100
+Subject: tty: Fix ->session locking
+
+From: Jann Horn <jannh@google.com>
+
+commit c8bcd9c5be24fb9e6132e97da5a35e55a83e36b9 upstream.
+
+Currently, locking of ->session is very inconsistent; most places
+protect it using the legacy tty mutex, but disassociate_ctty(),
+__do_SAK(), tiocspgrp() and tiocgsid() don't.
+Two of the writers hold the ctrl_lock (because they already need it for
+->pgrp), but __proc_set_tty() doesn't do that yet.
+
+On a PREEMPT=y system, an unprivileged user can theoretically abuse
+this broken locking to read 4 bytes of freed memory via TIOCGSID if
+tiocgsid() is preempted long enough at the right point. (Other things
+might also go wrong, especially if root-only ioctls are involved; I'm
+not sure about that.)
+
+Change the locking on ->session such that:
+
+ - tty_lock() is held by all writers: By making disassociate_ctty()
+   hold it. This should be fine because the same lock can already be
+   taken through the call to tty_vhangup_session().
+   The tricky part is that we need to shorten the area covered by
+   siglock to be able to take tty_lock() without ugly retry logic; as
+   far as I can tell, this should be fine, since nothing in the
+   signal_struct is touched in the `if (tty)` branch.
+ - ctrl_lock is held by all writers: By changing __proc_set_tty() to
+   hold the lock a little longer.
+ - All readers that aren't holding tty_lock() hold ctrl_lock: By
+   adding locking to tiocgsid() and __do_SAK(), and expanding the area
+   covered by ctrl_lock in tiocspgrp().
+
+Cc: stable@kernel.org
+Signed-off-by: Jann Horn <jannh@google.com>
+Reviewed-by: Jiri Slaby <jirislaby@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/tty_io.c |   51 +++++++++++++++++++++++++++++++++++++--------------
+ include/linux/tty.h  |    4 ++++
+ 2 files changed, 41 insertions(+), 14 deletions(-)
+
+--- a/drivers/tty/tty_io.c
++++ b/drivers/tty/tty_io.c
+@@ -537,8 +537,8 @@ static void __proc_set_tty(struct tty_st
+       put_pid(tty->session);
+       put_pid(tty->pgrp);
+       tty->pgrp = get_pid(task_pgrp(current));
+-      spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+       tty->session = get_pid(task_session(current));
++      spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+       if (current->signal->tty) {
+               tty_debug(tty, "current tty %s not NULL!!\n",
+                         current->signal->tty->name);
+@@ -929,21 +929,24 @@ void disassociate_ctty(int on_exit)
+       spin_lock_irq(&current->sighand->siglock);
+       put_pid(current->signal->tty_old_pgrp);
+       current->signal->tty_old_pgrp = NULL;
+-
+       tty = tty_kref_get(current->signal->tty);
++      spin_unlock_irq(&current->sighand->siglock);
++
+       if (tty) {
+               unsigned long flags;
++
++              tty_lock(tty);
+               spin_lock_irqsave(&tty->ctrl_lock, flags);
+               put_pid(tty->session);
+               put_pid(tty->pgrp);
+               tty->session = NULL;
+               tty->pgrp = NULL;
+               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
++              tty_unlock(tty);
+               tty_kref_put(tty);
+       } else
+               tty_debug_hangup(tty, "no current tty\n");
+-      spin_unlock_irq(&current->sighand->siglock);
+       /* Now clear signal->tty under the lock */
+       read_lock(&tasklist_lock);
+       session_clear_tty(task_session(current));
+@@ -2601,14 +2604,19 @@ static int tiocspgrp(struct tty_struct *
+               return -ENOTTY;
+       if (retval)
+               return retval;
+-      if (!current->signal->tty ||
+-          (current->signal->tty != real_tty) ||
+-          (real_tty->session != task_session(current)))
+-              return -ENOTTY;
++
+       if (get_user(pgrp_nr, p))
+               return -EFAULT;
+       if (pgrp_nr < 0)
+               return -EINVAL;
++
++      spin_lock_irq(&real_tty->ctrl_lock);
++      if (!current->signal->tty ||
++          (current->signal->tty != real_tty) ||
++          (real_tty->session != task_session(current))) {
++              retval = -ENOTTY;
++              goto out_unlock_ctrl;
++      }
+       rcu_read_lock();
+       pgrp = find_vpid(pgrp_nr);
+       retval = -ESRCH;
+@@ -2618,12 +2626,12 @@ static int tiocspgrp(struct tty_struct *
+       if (session_of_pgrp(pgrp) != task_session(current))
+               goto out_unlock;
+       retval = 0;
+-      spin_lock_irq(&real_tty->ctrl_lock);
+       put_pid(real_tty->pgrp);
+       real_tty->pgrp = get_pid(pgrp);
+-      spin_unlock_irq(&real_tty->ctrl_lock);
+ out_unlock:
+       rcu_read_unlock();
++out_unlock_ctrl:
++      spin_unlock_irq(&real_tty->ctrl_lock);
+       return retval;
+ }
+@@ -2635,21 +2643,31 @@ out_unlock:
+  *
+  *    Obtain the session id of the tty. If there is no session
+  *    return an error.
+- *
+- *    Locking: none. Reference to current->signal->tty is safe.
+  */
+ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
+ {
++      unsigned long flags;
++      pid_t sid;
++
+       /*
+        * (tty == real_tty) is a cheap way of
+        * testing if the tty is NOT a master pty.
+       */
+       if (tty == real_tty && current->signal->tty != real_tty)
+               return -ENOTTY;
++
++      spin_lock_irqsave(&real_tty->ctrl_lock, flags);
+       if (!real_tty->session)
+-              return -ENOTTY;
+-      return put_user(pid_vnr(real_tty->session), p);
++              goto err;
++      sid = pid_vnr(real_tty->session);
++      spin_unlock_irqrestore(&real_tty->ctrl_lock, flags);
++
++      return put_user(sid, p);
++
++err:
++      spin_unlock_irqrestore(&real_tty->ctrl_lock, flags);
++      return -ENOTTY;
+ }
+ /**
+@@ -3061,10 +3079,14 @@ void __do_SAK(struct tty_struct *tty)
+       struct task_struct *g, *p;
+       struct pid *session;
+       int             i;
++      unsigned long flags;
+       if (!tty)
+               return;
+-      session = tty->session;
++
++      spin_lock_irqsave(&tty->ctrl_lock, flags);
++      session = get_pid(tty->session);
++      spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+       tty_ldisc_flush(tty);
+@@ -3100,6 +3122,7 @@ void __do_SAK(struct tty_struct *tty)
+               task_unlock(p);
+       } while_each_thread(g, p);
+       read_unlock(&tasklist_lock);
++      put_pid(session);
+ #endif
+ }
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -280,6 +280,10 @@ struct tty_struct {
+       struct termiox *termiox;        /* May be NULL for unsupported */
+       char name[64];
+       struct pid *pgrp;               /* Protected by ctrl lock */
++      /*
++       * Writes protected by both ctrl lock and legacy mutex, readers must use
++       * at least one of them.
++       */
+       struct pid *session;
+       unsigned long flags;
+       int count;