linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, stable@kernel.org,
	Jann Horn <jannh@google.com>, Jiri Slaby <jirislaby@kernel.org>
Subject: [PATCH 5.9 09/75] tty: Fix ->session locking
Date: Thu, 10 Dec 2020 15:26:34 +0100	[thread overview]
Message-ID: <20201210142606.529534239@linuxfoundation.org> (raw)
In-Reply-To: <20201210142606.074509102@linuxfoundation.org>

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      |    7 ++++++-
 drivers/tty/tty_jobctrl.c |   44 +++++++++++++++++++++++++++++++-------------
 include/linux/tty.h       |    4 ++++
 3 files changed, 41 insertions(+), 14 deletions(-)

--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -2899,10 +2899,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);
 
@@ -2934,6 +2938,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/drivers/tty/tty_jobctrl.c
+++ b/drivers/tty/tty_jobctrl.c
@@ -103,8 +103,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);
@@ -293,20 +293,23 @@ 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);
 	}
 
-	spin_unlock_irq(&current->sighand->siglock);
 	/* Now clear signal->tty under the lock */
 	read_lock(&tasklist_lock);
 	session_clear_tty(task_session(current));
@@ -477,14 +480,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;
@@ -494,12 +502,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;
 }
 
@@ -511,20 +519,30 @@ 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;
 }
 
 /*
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -306,6 +306,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;



  parent reply	other threads:[~2020-12-10 15:22 UTC|newest]

Thread overview: 83+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-10 14:26 [PATCH 5.9 00/75] 5.9.14-rc1 review Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 01/75] usb: gadget: f_fs: Use local copy of descriptors for userspace copy Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 02/75] USB: serial: kl5kusb105: fix memleak on open Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 03/75] USB: serial: ch341: add new Product ID for CH341A Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 04/75] USB: serial: ch341: sort device-id entries Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 05/75] USB: serial: option: add Fibocom NL668 variants Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 06/75] USB: serial: option: add support for Thales Cinterion EXS82 Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 07/75] USB: serial: option: fix Quectel BG96 matching Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 08/75] tty: Fix ->pgrp locking in tiocspgrp() Greg Kroah-Hartman
2020-12-10 14:26 ` Greg Kroah-Hartman [this message]
2020-12-10 14:26 ` [PATCH 5.9 10/75] speakup: Reject setting the speakup line discipline outside of speakup Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 11/75] ALSA: hda/realtek: Fix bass speaker DAC assignment on Asus Zephyrus G14 Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 12/75] ALSA: hda/realtek: Add mute LED quirk to yet another HP x360 model Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 13/75] ALSA: hda/realtek: Enable headset of ASUS UX482EG & B9400CEA with ALC294 Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 14/75] ALSA: hda/realtek - Add new codec supported for ALC897 Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 15/75] ALSA: hda/realtek - Fixed Dell AIO wrong sound tone Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 16/75] ALSA: hda/generic: Add option to enforce preferred_dacs pairs Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 17/75] ring-buffer: Update write stamp with the correct ts Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 18/75] ring-buffer: Set the right timestamp in the slow path of __rb_reserve_next() Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 19/75] ring-buffer: Always check to put back before stamp when crossing pages Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 20/75] ftrace: Fix updating FTRACE_FL_TRAMP Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 21/75] ftrace: Fix DYNAMIC_FTRACE_WITH_DIRECT_CALLS dependency Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 22/75] cifs: allow syscalls to be restarted in __smb_send_rqst() Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 23/75] cifs: fix potential use-after-free in cifs_echo_request() Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 24/75] cifs: refactor create_sd_buf() and and avoid corrupting the buffer Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 25/75] cifs: add NULL check for ses->tcon_ipc Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 26/75] gfs2: Upgrade shared glocks for atime updates Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 27/75] gfs2: Fix deadlock between gfs2_{create_inode,inode_lookup} and delete_work_func Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 28/75] s390/pci: fix CPU address in MSI for directed IRQ Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 29/75] i2c: imx: Fix reset of I2SR_IAL flag Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 30/75] i2c: imx: Check for I2SR_IAL after every byte Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 31/75] i2c: imx: Dont generate STOP condition if arbitration has been lost Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 32/75] tracing: Fix userstacktrace option for instances Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 33/75] thunderbolt: Fix use-after-free in remove_unplugged_switch() Greg Kroah-Hartman
2020-12-10 14:26 ` [PATCH 5.9 34/75] drm/omap: sdi: fix bridge enable/disable Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 35/75] drm/amdgpu/vcn3.0: stall DPG when WPTR/RPTR reset Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 36/75] drm/amdgpu/vcn3.0: remove old DPG workaround Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 37/75] drm/i915/gt: Retain default context state across shrinking Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 38/75] drm/i915/gt: Limit frequency drop to RPe on parking Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 39/75] drm/i915/gt: Program mocs:63 for cache eviction on gen9 Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 40/75] KVM: PPC: Book3S HV: XIVE: Fix vCPU id sanity check Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 41/75] scsi: mpt3sas: Fix ioctl timeout Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 42/75] io_uring: fix recvmsg setup with compat buf-select Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 43/75] dm writecache: advance the number of arguments when reporting max_age Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 44/75] dm writecache: fix the maximum number of arguments Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 45/75] powerpc/64s/powernv: Fix memory corruption when saving SLB entries on MCE Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 46/75] genirq/irqdomain: Add an irq_create_mapping_affinity() function Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 47/75] powerpc/pseries: Pass MSI affinity to irq_create_mapping() Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 48/75] dm: fix bug with RCU locking in dm_blk_report_zones Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 49/75] dm: fix double RCU unlock in dm_dax_zero_page_range() error path Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 50/75] dm: remove invalid sparse __acquires and __releases annotations Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 51/75] x86/uprobes: Do not use prefixes.nbytes when looping over prefixes.bytes Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 52/75] coredump: fix core_pattern parse error Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 53/75] mm: list_lru: set shrinker map bit when child nr_items is not zero Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 54/75] mm/swapfile: do not sleep with a spin lock held Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 55/75] hugetlb_cgroup: fix offline of hugetlb cgroup with reservations Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 56/75] [PATCH] Revert "amd/amdgpu: Disable VCN DPG mode for Picasso" Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 57/75] iommu/amd: Set DTE[IntTabLen] to represent 512 IRTEs Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 58/75] mm: memcg/slab: fix obj_cgroup_charge() return value handling Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 59/75] lib/syscall: fix syscall registers retrieval on 32-bit platforms Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 60/75] can: af_can: can_rx_unregister(): remove WARN() statement from list operation sanity check Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 61/75] gfs2: check for empty rgrp tree in gfs2_ri_update Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 62/75] netfilter: ipset: prevent uninit-value in hash_ip6_add Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 63/75] tipc: fix a deadlock when flushing scheduled work Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 64/75] ASoC: wm_adsp: fix error return code in wm_adsp_load() Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 65/75] gfs2: Fix deadlock dumping resource group glocks Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 66/75] gfs2: Dont freeze the file system during unmount Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 67/75] rtw88: debug: Fix uninitialized memory in debugfs code Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 68/75] i2c: qcom: Fix IRQ error misassignement Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 69/75] i2c: qup: Fix error return code in qup_i2c_bam_schedule_desc() Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 70/75] dm writecache: remove BUG() and fail gracefully instead Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 71/75] Input: i8042 - fix error return code in i8042_setup_aux() Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 72/75] netfilter: nf_tables: avoid false-postive lockdep splat Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 73/75] netfilter: nftables_offload: set address type in control dissector Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 74/75] netfilter: nftables_offload: build mask based from the matching bytes Greg Kroah-Hartman
2020-12-10 14:27 ` [PATCH 5.9 75/75] x86/insn-eval: Use new for_each_insn_prefix() macro to loop over prefixes bytes Greg Kroah-Hartman
2020-12-10 21:20 ` [PATCH 5.9 00/75] 5.9.14-rc1 review Shuah Khan
2020-12-11 14:23   ` Greg Kroah-Hartman
2020-12-10 21:24 ` Jeffrin Jose T
2020-12-10 23:46 ` Guenter Roeck
2020-12-11 14:23   ` Greg Kroah-Hartman
2020-12-11  5:31 ` Naresh Kamboju
2020-12-11 14:22   ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201210142606.529534239@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=jannh@google.com \
    --cc=jirislaby@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).