cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

tty_jobctrl.c (14912B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 *  Copyright (C) 1991, 1992  Linus Torvalds
      4 */
      5
      6#include <linux/types.h>
      7#include <linux/errno.h>
      8#include <linux/signal.h>
      9#include <linux/sched/signal.h>
     10#include <linux/sched/task.h>
     11#include <linux/tty.h>
     12#include <linux/fcntl.h>
     13#include <linux/uaccess.h>
     14#include "tty.h"
     15
     16static int is_ignored(int sig)
     17{
     18	return (sigismember(&current->blocked, sig) ||
     19		current->sighand->action[sig-1].sa.sa_handler == SIG_IGN);
     20}
     21
     22/**
     23 *	__tty_check_change	-	check for POSIX terminal changes
     24 *	@tty: tty to check
     25 *	@sig: signal to send
     26 *
     27 *	If we try to write to, or set the state of, a terminal and we're
     28 *	not in the foreground, send a SIGTTOU.  If the signal is blocked or
     29 *	ignored, go ahead and perform the operation.  (POSIX 7.2)
     30 *
     31 *	Locking: ctrl.lock
     32 */
     33int __tty_check_change(struct tty_struct *tty, int sig)
     34{
     35	unsigned long flags;
     36	struct pid *pgrp, *tty_pgrp;
     37	int ret = 0;
     38
     39	if (current->signal->tty != tty)
     40		return 0;
     41
     42	rcu_read_lock();
     43	pgrp = task_pgrp(current);
     44
     45	spin_lock_irqsave(&tty->ctrl.lock, flags);
     46	tty_pgrp = tty->ctrl.pgrp;
     47	spin_unlock_irqrestore(&tty->ctrl.lock, flags);
     48
     49	if (tty_pgrp && pgrp != tty_pgrp) {
     50		if (is_ignored(sig)) {
     51			if (sig == SIGTTIN)
     52				ret = -EIO;
     53		} else if (is_current_pgrp_orphaned())
     54			ret = -EIO;
     55		else {
     56			kill_pgrp(pgrp, sig, 1);
     57			set_thread_flag(TIF_SIGPENDING);
     58			ret = -ERESTARTSYS;
     59		}
     60	}
     61	rcu_read_unlock();
     62
     63	if (!tty_pgrp)
     64		tty_warn(tty, "sig=%d, tty->pgrp == NULL!\n", sig);
     65
     66	return ret;
     67}
     68
     69int tty_check_change(struct tty_struct *tty)
     70{
     71	return __tty_check_change(tty, SIGTTOU);
     72}
     73EXPORT_SYMBOL(tty_check_change);
     74
     75void proc_clear_tty(struct task_struct *p)
     76{
     77	unsigned long flags;
     78	struct tty_struct *tty;
     79
     80	spin_lock_irqsave(&p->sighand->siglock, flags);
     81	tty = p->signal->tty;
     82	p->signal->tty = NULL;
     83	spin_unlock_irqrestore(&p->sighand->siglock, flags);
     84	tty_kref_put(tty);
     85}
     86
     87/**
     88 * __proc_set_tty -  set the controlling terminal
     89 *	@tty: tty structure
     90 *
     91 * Only callable by the session leader and only if it does not already have
     92 * a controlling terminal.
     93 *
     94 * Caller must hold:  tty_lock()
     95 *		      a readlock on tasklist_lock
     96 *		      sighand lock
     97 */
     98static void __proc_set_tty(struct tty_struct *tty)
     99{
    100	unsigned long flags;
    101
    102	spin_lock_irqsave(&tty->ctrl.lock, flags);
    103	/*
    104	 * The session and fg pgrp references will be non-NULL if
    105	 * tiocsctty() is stealing the controlling tty
    106	 */
    107	put_pid(tty->ctrl.session);
    108	put_pid(tty->ctrl.pgrp);
    109	tty->ctrl.pgrp = get_pid(task_pgrp(current));
    110	tty->ctrl.session = get_pid(task_session(current));
    111	spin_unlock_irqrestore(&tty->ctrl.lock, flags);
    112	if (current->signal->tty) {
    113		tty_debug(tty, "current tty %s not NULL!!\n",
    114			  current->signal->tty->name);
    115		tty_kref_put(current->signal->tty);
    116	}
    117	put_pid(current->signal->tty_old_pgrp);
    118	current->signal->tty = tty_kref_get(tty);
    119	current->signal->tty_old_pgrp = NULL;
    120}
    121
    122static void proc_set_tty(struct tty_struct *tty)
    123{
    124	spin_lock_irq(&current->sighand->siglock);
    125	__proc_set_tty(tty);
    126	spin_unlock_irq(&current->sighand->siglock);
    127}
    128
    129/*
    130 * Called by tty_open() to set the controlling tty if applicable.
    131 */
    132void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty)
    133{
    134	read_lock(&tasklist_lock);
    135	spin_lock_irq(&current->sighand->siglock);
    136	if (current->signal->leader &&
    137	    !current->signal->tty &&
    138	    tty->ctrl.session == NULL) {
    139		/*
    140		 * Don't let a process that only has write access to the tty
    141		 * obtain the privileges associated with having a tty as
    142		 * controlling terminal (being able to reopen it with full
    143		 * access through /dev/tty, being able to perform pushback).
    144		 * Many distributions set the group of all ttys to "tty" and
    145		 * grant write-only access to all terminals for setgid tty
    146		 * binaries, which should not imply full privileges on all ttys.
    147		 *
    148		 * This could theoretically break old code that performs open()
    149		 * on a write-only file descriptor. In that case, it might be
    150		 * necessary to also permit this if
    151		 * inode_permission(inode, MAY_READ) == 0.
    152		 */
    153		if (filp->f_mode & FMODE_READ)
    154			__proc_set_tty(tty);
    155	}
    156	spin_unlock_irq(&current->sighand->siglock);
    157	read_unlock(&tasklist_lock);
    158}
    159
    160struct tty_struct *get_current_tty(void)
    161{
    162	struct tty_struct *tty;
    163	unsigned long flags;
    164
    165	spin_lock_irqsave(&current->sighand->siglock, flags);
    166	tty = tty_kref_get(current->signal->tty);
    167	spin_unlock_irqrestore(&current->sighand->siglock, flags);
    168	return tty;
    169}
    170EXPORT_SYMBOL_GPL(get_current_tty);
    171
    172/*
    173 * Called from tty_release().
    174 */
    175void session_clear_tty(struct pid *session)
    176{
    177	struct task_struct *p;
    178
    179	do_each_pid_task(session, PIDTYPE_SID, p) {
    180		proc_clear_tty(p);
    181	} while_each_pid_task(session, PIDTYPE_SID, p);
    182}
    183
    184/**
    185 *	tty_signal_session_leader	- sends SIGHUP to session leader
    186 *	@tty: controlling tty
    187 *	@exit_session: if non-zero, signal all foreground group processes
    188 *
    189 *	Send SIGHUP and SIGCONT to the session leader and its process group.
    190 *	Optionally, signal all processes in the foreground process group.
    191 *
    192 *	Returns the number of processes in the session with this tty
    193 *	as their controlling terminal. This value is used to drop
    194 *	tty references for those processes.
    195 */
    196int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
    197{
    198	struct task_struct *p;
    199	int refs = 0;
    200	struct pid *tty_pgrp = NULL;
    201
    202	read_lock(&tasklist_lock);
    203	if (tty->ctrl.session) {
    204		do_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p) {
    205			spin_lock_irq(&p->sighand->siglock);
    206			if (p->signal->tty == tty) {
    207				p->signal->tty = NULL;
    208				/*
    209				 * We defer the dereferences outside of
    210				 * the tasklist lock.
    211				 */
    212				refs++;
    213			}
    214			if (!p->signal->leader) {
    215				spin_unlock_irq(&p->sighand->siglock);
    216				continue;
    217			}
    218			send_signal_locked(SIGHUP, SEND_SIG_PRIV, p, PIDTYPE_TGID);
    219			send_signal_locked(SIGCONT, SEND_SIG_PRIV, p, PIDTYPE_TGID);
    220			put_pid(p->signal->tty_old_pgrp);  /* A noop */
    221			spin_lock(&tty->ctrl.lock);
    222			tty_pgrp = get_pid(tty->ctrl.pgrp);
    223			if (tty->ctrl.pgrp)
    224				p->signal->tty_old_pgrp =
    225					get_pid(tty->ctrl.pgrp);
    226			spin_unlock(&tty->ctrl.lock);
    227			spin_unlock_irq(&p->sighand->siglock);
    228		} while_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p);
    229	}
    230	read_unlock(&tasklist_lock);
    231
    232	if (tty_pgrp) {
    233		if (exit_session)
    234			kill_pgrp(tty_pgrp, SIGHUP, exit_session);
    235		put_pid(tty_pgrp);
    236	}
    237
    238	return refs;
    239}
    240
    241/**
    242 *	disassociate_ctty	-	disconnect controlling tty
    243 *	@on_exit: true if exiting so need to "hang up" the session
    244 *
    245 *	This function is typically called only by the session leader, when
    246 *	it wants to disassociate itself from its controlling tty.
    247 *
    248 *	It performs the following functions:
    249 *	(1)  Sends a SIGHUP and SIGCONT to the foreground process group
    250 *	(2)  Clears the tty from being controlling the session
    251 *	(3)  Clears the controlling tty for all processes in the
    252 *		session group.
    253 *
    254 *	The argument on_exit is set to 1 if called when a process is
    255 *	exiting; it is 0 if called by the ioctl TIOCNOTTY.
    256 *
    257 *	Locking:
    258 *		BTM is taken for hysterical raisons, and held when
    259 *		  called from no_tty().
    260 *		  tty_mutex is taken to protect tty
    261 *		  ->siglock is taken to protect ->signal/->sighand
    262 *		  tasklist_lock is taken to walk process list for sessions
    263 *		    ->siglock is taken to protect ->signal/->sighand
    264 */
    265void disassociate_ctty(int on_exit)
    266{
    267	struct tty_struct *tty;
    268
    269	if (!current->signal->leader)
    270		return;
    271
    272	tty = get_current_tty();
    273	if (tty) {
    274		if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) {
    275			tty_vhangup_session(tty);
    276		} else {
    277			struct pid *tty_pgrp = tty_get_pgrp(tty);
    278
    279			if (tty_pgrp) {
    280				kill_pgrp(tty_pgrp, SIGHUP, on_exit);
    281				if (!on_exit)
    282					kill_pgrp(tty_pgrp, SIGCONT, on_exit);
    283				put_pid(tty_pgrp);
    284			}
    285		}
    286		tty_kref_put(tty);
    287
    288	} else if (on_exit) {
    289		struct pid *old_pgrp;
    290
    291		spin_lock_irq(&current->sighand->siglock);
    292		old_pgrp = current->signal->tty_old_pgrp;
    293		current->signal->tty_old_pgrp = NULL;
    294		spin_unlock_irq(&current->sighand->siglock);
    295		if (old_pgrp) {
    296			kill_pgrp(old_pgrp, SIGHUP, on_exit);
    297			kill_pgrp(old_pgrp, SIGCONT, on_exit);
    298			put_pid(old_pgrp);
    299		}
    300		return;
    301	}
    302
    303	spin_lock_irq(&current->sighand->siglock);
    304	put_pid(current->signal->tty_old_pgrp);
    305	current->signal->tty_old_pgrp = NULL;
    306	tty = tty_kref_get(current->signal->tty);
    307	spin_unlock_irq(&current->sighand->siglock);
    308
    309	if (tty) {
    310		unsigned long flags;
    311
    312		tty_lock(tty);
    313		spin_lock_irqsave(&tty->ctrl.lock, flags);
    314		put_pid(tty->ctrl.session);
    315		put_pid(tty->ctrl.pgrp);
    316		tty->ctrl.session = NULL;
    317		tty->ctrl.pgrp = NULL;
    318		spin_unlock_irqrestore(&tty->ctrl.lock, flags);
    319		tty_unlock(tty);
    320		tty_kref_put(tty);
    321	}
    322
    323	/* Now clear signal->tty under the lock */
    324	read_lock(&tasklist_lock);
    325	session_clear_tty(task_session(current));
    326	read_unlock(&tasklist_lock);
    327}
    328
    329/*
    330 *
    331 *	no_tty	- Ensure the current process does not have a controlling tty
    332 */
    333void no_tty(void)
    334{
    335	/*
    336	 * FIXME: Review locking here. The tty_lock never covered any race
    337	 * between a new association and proc_clear_tty but possibly we need
    338	 * to protect against this anyway.
    339	 */
    340	struct task_struct *tsk = current;
    341
    342	disassociate_ctty(0);
    343	proc_clear_tty(tsk);
    344}
    345
    346/**
    347 *	tiocsctty	-	set controlling tty
    348 *	@tty: tty structure
    349 *	@file: file structure used to check permissions
    350 *	@arg: user argument
    351 *
    352 *	This ioctl is used to manage job control. It permits a session
    353 *	leader to set this tty as the controlling tty for the session.
    354 *
    355 *	Locking:
    356 *		Takes tty_lock() to serialize proc_set_tty() for this tty
    357 *		Takes tasklist_lock internally to walk sessions
    358 *		Takes ->siglock() when updating signal->tty
    359 */
    360static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
    361{
    362	int ret = 0;
    363
    364	tty_lock(tty);
    365	read_lock(&tasklist_lock);
    366
    367	if (current->signal->leader &&
    368			task_session(current) == tty->ctrl.session)
    369		goto unlock;
    370
    371	/*
    372	 * The process must be a session leader and
    373	 * not have a controlling tty already.
    374	 */
    375	if (!current->signal->leader || current->signal->tty) {
    376		ret = -EPERM;
    377		goto unlock;
    378	}
    379
    380	if (tty->ctrl.session) {
    381		/*
    382		 * This tty is already the controlling
    383		 * tty for another session group!
    384		 */
    385		if (arg == 1 && capable(CAP_SYS_ADMIN)) {
    386			/*
    387			 * Steal it away
    388			 */
    389			session_clear_tty(tty->ctrl.session);
    390		} else {
    391			ret = -EPERM;
    392			goto unlock;
    393		}
    394	}
    395
    396	/* See the comment in tty_open_proc_set_tty(). */
    397	if ((file->f_mode & FMODE_READ) == 0 && !capable(CAP_SYS_ADMIN)) {
    398		ret = -EPERM;
    399		goto unlock;
    400	}
    401
    402	proc_set_tty(tty);
    403unlock:
    404	read_unlock(&tasklist_lock);
    405	tty_unlock(tty);
    406	return ret;
    407}
    408
    409/**
    410 *	tty_get_pgrp	-	return a ref counted pgrp pid
    411 *	@tty: tty to read
    412 *
    413 *	Returns a refcounted instance of the pid struct for the process
    414 *	group controlling the tty.
    415 */
    416struct pid *tty_get_pgrp(struct tty_struct *tty)
    417{
    418	unsigned long flags;
    419	struct pid *pgrp;
    420
    421	spin_lock_irqsave(&tty->ctrl.lock, flags);
    422	pgrp = get_pid(tty->ctrl.pgrp);
    423	spin_unlock_irqrestore(&tty->ctrl.lock, flags);
    424
    425	return pgrp;
    426}
    427EXPORT_SYMBOL_GPL(tty_get_pgrp);
    428
    429/*
    430 * This checks not only the pgrp, but falls back on the pid if no
    431 * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
    432 * without this...
    433 *
    434 * The caller must hold rcu lock or the tasklist lock.
    435 */
    436static struct pid *session_of_pgrp(struct pid *pgrp)
    437{
    438	struct task_struct *p;
    439	struct pid *sid = NULL;
    440
    441	p = pid_task(pgrp, PIDTYPE_PGID);
    442	if (p == NULL)
    443		p = pid_task(pgrp, PIDTYPE_PID);
    444	if (p != NULL)
    445		sid = task_session(p);
    446
    447	return sid;
    448}
    449
    450/**
    451 *	tiocgpgrp		-	get process group
    452 *	@tty: tty passed by user
    453 *	@real_tty: tty side of the tty passed by the user if a pty else the tty
    454 *	@p: returned pid
    455 *
    456 *	Obtain the process group of the tty. If there is no process group
    457 *	return an error.
    458 *
    459 *	Locking: none. Reference to current->signal->tty is safe.
    460 */
    461static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
    462{
    463	struct pid *pid;
    464	int ret;
    465	/*
    466	 * (tty == real_tty) is a cheap way of
    467	 * testing if the tty is NOT a master pty.
    468	 */
    469	if (tty == real_tty && current->signal->tty != real_tty)
    470		return -ENOTTY;
    471	pid = tty_get_pgrp(real_tty);
    472	ret =  put_user(pid_vnr(pid), p);
    473	put_pid(pid);
    474	return ret;
    475}
    476
    477/**
    478 *	tiocspgrp		-	attempt to set process group
    479 *	@tty: tty passed by user
    480 *	@real_tty: tty side device matching tty passed by user
    481 *	@p: pid pointer
    482 *
    483 *	Set the process group of the tty to the session passed. Only
    484 *	permitted where the tty session is our session.
    485 *
    486 *	Locking: RCU, ctrl lock
    487 */
    488static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
    489{
    490	struct pid *pgrp;
    491	pid_t pgrp_nr;
    492	int retval = tty_check_change(real_tty);
    493
    494	if (retval == -EIO)
    495		return -ENOTTY;
    496	if (retval)
    497		return retval;
    498
    499	if (get_user(pgrp_nr, p))
    500		return -EFAULT;
    501	if (pgrp_nr < 0)
    502		return -EINVAL;
    503
    504	spin_lock_irq(&real_tty->ctrl.lock);
    505	if (!current->signal->tty ||
    506	    (current->signal->tty != real_tty) ||
    507	    (real_tty->ctrl.session != task_session(current))) {
    508		retval = -ENOTTY;
    509		goto out_unlock_ctrl;
    510	}
    511	rcu_read_lock();
    512	pgrp = find_vpid(pgrp_nr);
    513	retval = -ESRCH;
    514	if (!pgrp)
    515		goto out_unlock;
    516	retval = -EPERM;
    517	if (session_of_pgrp(pgrp) != task_session(current))
    518		goto out_unlock;
    519	retval = 0;
    520	put_pid(real_tty->ctrl.pgrp);
    521	real_tty->ctrl.pgrp = get_pid(pgrp);
    522out_unlock:
    523	rcu_read_unlock();
    524out_unlock_ctrl:
    525	spin_unlock_irq(&real_tty->ctrl.lock);
    526	return retval;
    527}
    528
    529/**
    530 *	tiocgsid		-	get session id
    531 *	@tty: tty passed by user
    532 *	@real_tty: tty side of the tty passed by the user if a pty else the tty
    533 *	@p: pointer to returned session id
    534 *
    535 *	Obtain the session id of the tty. If there is no session
    536 *	return an error.
    537 */
    538static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
    539{
    540	unsigned long flags;
    541	pid_t sid;
    542
    543	/*
    544	 * (tty == real_tty) is a cheap way of
    545	 * testing if the tty is NOT a master pty.
    546	 */
    547	if (tty == real_tty && current->signal->tty != real_tty)
    548		return -ENOTTY;
    549
    550	spin_lock_irqsave(&real_tty->ctrl.lock, flags);
    551	if (!real_tty->ctrl.session)
    552		goto err;
    553	sid = pid_vnr(real_tty->ctrl.session);
    554	spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
    555
    556	return put_user(sid, p);
    557
    558err:
    559	spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
    560	return -ENOTTY;
    561}
    562
    563/*
    564 * Called from tty_ioctl(). If tty is a pty then real_tty is the slave side,
    565 * if not then tty == real_tty.
    566 */
    567long tty_jobctrl_ioctl(struct tty_struct *tty, struct tty_struct *real_tty,
    568		       struct file *file, unsigned int cmd, unsigned long arg)
    569{
    570	void __user *p = (void __user *)arg;
    571
    572	switch (cmd) {
    573	case TIOCNOTTY:
    574		if (current->signal->tty != tty)
    575			return -ENOTTY;
    576		no_tty();
    577		return 0;
    578	case TIOCSCTTY:
    579		return tiocsctty(real_tty, file, arg);
    580	case TIOCGPGRP:
    581		return tiocgpgrp(tty, real_tty, p);
    582	case TIOCSPGRP:
    583		return tiocspgrp(tty, real_tty, p);
    584	case TIOCGSID:
    585		return tiocgsid(tty, real_tty, p);
    586	}
    587	return -ENOIOCTLCMD;
    588}