From: Greg Kroah-Hartman Date: Wed, 9 Dec 2020 08:45:58 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v5.9.14~48 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=98cf47178e5100b9a813be98f0e642059cedc41f;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: cifs-fix-potential-use-after-free-in-cifs_echo_request.patch ftrace-fix-updating-ftrace_fl_tramp.patch powerpc-pseries-pass-msi-affinity-to-irq_create_mapping.patch tty-fix-session-locking.patch --- diff --git a/queue-4.9/cifs-fix-potential-use-after-free-in-cifs_echo_request.patch b/queue-4.9/cifs-fix-potential-use-after-free-in-cifs_echo_request.patch new file mode 100644 index 00000000000..b01078be7dc --- /dev/null +++ b/queue-4.9/cifs-fix-potential-use-after-free-in-cifs_echo_request.patch @@ -0,0 +1,51 @@ +From 212253367dc7b49ed3fc194ce71b0992eacaecf2 Mon Sep 17 00:00:00 2001 +From: Paulo Alcantara +Date: Sat, 28 Nov 2020 16:54:02 -0300 +Subject: cifs: fix potential use-after-free in cifs_echo_request() + +From: Paulo Alcantara + +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) +CC: Stable +Reviewed-by: Ronnie Sahlberg +Signed-off-by: Steve French +Signed-off-by: Greg Kroah-Hartman + +--- + fs/cifs/connect.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/fs/cifs/connect.c ++++ b/fs/cifs/connect.c +@@ -730,6 +730,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.9/ftrace-fix-updating-ftrace_fl_tramp.patch b/queue-4.9/ftrace-fix-updating-ftrace_fl_tramp.patch new file mode 100644 index 00000000000..dd8659464e2 --- /dev/null +++ b/queue-4.9/ftrace-fix-updating-ftrace_fl_tramp.patch @@ -0,0 +1,86 @@ +From 4c75b0ff4e4bf7a45b5aef9639799719c28d0073 Mon Sep 17 00:00:00 2001 +From: "Naveen N. Rao" +Date: Thu, 26 Nov 2020 23:38:38 +0530 +Subject: ftrace: Fix updating FTRACE_FL_TRAMP + +From: Naveen N. Rao + +commit 4c75b0ff4e4bf7a45b5aef9639799719c28d0073 upstream. + +On powerpc, kprobe-direct.tc triggered FTRACE_WARN_ON() in +ftrace_get_addr_new() followed by the below message: + Bad trampoline accounting at: 000000004222522f (wake_up_process+0xc/0x20) (f0000001) + +The set of steps leading to this involved: +- modprobe ftrace-direct-too +- enable_probe +- modprobe ftrace-direct +- rmmod ftrace-direct <-- trigger + +The problem turned out to be that we were not updating flags in the +ftrace record properly. From the above message about the trampoline +accounting being bad, it can be seen that the ftrace record still has +FTRACE_FL_TRAMP set though ftrace-direct module is going away. This +happens because we are checking if any ftrace_ops has the +FTRACE_FL_TRAMP flag set _before_ updating the filter hash. + +The fix for this is to look for any _other_ ftrace_ops that also needs +FTRACE_FL_TRAMP. + +Link: https://lkml.kernel.org/r/56c113aa9c3e10c19144a36d9684c7882bf09af5.1606412433.git.naveen.n.rao@linux.vnet.ibm.com + +Cc: stable@vger.kernel.org +Fixes: a124692b698b0 ("ftrace: Enable trampoline when rec count returns back to one") +Signed-off-by: Naveen N. Rao +Signed-off-by: Steven Rostedt (VMware) +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/trace/ftrace.c | 22 +++++++++++++++++++++- + 1 file changed, 21 insertions(+), 1 deletion(-) + +--- a/kernel/trace/ftrace.c ++++ b/kernel/trace/ftrace.c +@@ -1634,6 +1634,8 @@ static bool test_rec_ops_needs_regs(stru + static struct ftrace_ops * + ftrace_find_tramp_ops_any(struct dyn_ftrace *rec); + static struct ftrace_ops * ++ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude); ++static struct ftrace_ops * + ftrace_find_tramp_ops_next(struct dyn_ftrace *rec, struct ftrace_ops *ops); + + static bool __ftrace_hash_rec_update(struct ftrace_ops *ops, +@@ -1771,7 +1773,7 @@ static bool __ftrace_hash_rec_update(str + * to it. + */ + if (ftrace_rec_count(rec) == 1 && +- ftrace_find_tramp_ops_any(rec)) ++ ftrace_find_tramp_ops_any_other(rec, ops)) + rec->flags |= FTRACE_FL_TRAMP; + else + rec->flags &= ~FTRACE_FL_TRAMP; +@@ -2193,6 +2195,24 @@ ftrace_find_tramp_ops_any(struct dyn_ftr + continue; + + if (hash_contains_ip(ip, op->func_hash)) ++ return op; ++ } while_for_each_ftrace_op(op); ++ ++ return NULL; ++} ++ ++static struct ftrace_ops * ++ftrace_find_tramp_ops_any_other(struct dyn_ftrace *rec, struct ftrace_ops *op_exclude) ++{ ++ struct ftrace_ops *op; ++ unsigned long ip = rec->ip; ++ ++ do_for_each_ftrace_op(op, ftrace_ops_list) { ++ ++ if (op == op_exclude || !op->trampoline) ++ continue; ++ ++ if (hash_contains_ip(ip, op->func_hash)) + return op; + } while_for_each_ftrace_op(op); + diff --git a/queue-4.9/powerpc-pseries-pass-msi-affinity-to-irq_create_mapping.patch b/queue-4.9/powerpc-pseries-pass-msi-affinity-to-irq_create_mapping.patch new file mode 100644 index 00000000000..c7adf3c5058 --- /dev/null +++ b/queue-4.9/powerpc-pseries-pass-msi-affinity-to-irq_create_mapping.patch @@ -0,0 +1,54 @@ +From 9ea69a55b3b9a71cded9726af591949c1138f235 Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Thu, 26 Nov 2020 09:28:52 +0100 +Subject: powerpc/pseries: Pass MSI affinity to irq_create_mapping() + +From: Laurent Vivier + +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 +Signed-off-by: Thomas Gleixner +Reviewed-by: Greg Kurz +Acked-by: Michael Ellerman +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/r/20201126082852.1178497-3-lvivier@redhat.com +Signed-off-by: Greg Kroah-Hartman + +--- + 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) { + pr_debug("rtas_msi: Failed mapping hwirq %d\n", hwirq); diff --git a/queue-4.9/series b/queue-4.9/series index 7c89e276994..9995de53353 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -28,3 +28,7 @@ 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 +ftrace-fix-updating-ftrace_fl_tramp.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.9/tty-fix-session-locking.patch b/queue-4.9/tty-fix-session-locking.patch new file mode 100644 index 00000000000..19b37167be4 --- /dev/null +++ b/queue-4.9/tty-fix-session-locking.patch @@ -0,0 +1,197 @@ +From c8bcd9c5be24fb9e6132e97da5a35e55a83e36b9 Mon Sep 17 00:00:00 2001 +From: Jann Horn +Date: Thu, 3 Dec 2020 02:25:05 +0100 +Subject: tty: Fix ->session locking + +From: Jann Horn + +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 +Reviewed-by: Jiri Slaby +Signed-off-by: Greg Kroah-Hartman + +--- + 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 +@@ -544,8 +544,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); +@@ -935,21 +935,24 @@ void disassociate_ctty(int on_exit) + spin_lock_irq(¤t->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(¤t->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(¤t->sighand->siglock); + /* Now clear signal->tty under the lock */ + read_lock(&tasklist_lock); + session_clear_tty(task_session(current)); +@@ -2628,14 +2631,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; +@@ -2645,12 +2653,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; + } + +@@ -2662,21 +2670,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; + } + + /** +@@ -3094,10 +3112,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); + +@@ -3129,6 +3151,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 +@@ -293,6 +293,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;