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