LCOV - code coverage report
Current view: top level - tty - tty_jobctrl.c (source / functions) Coverage Total Hit
Test: TTY Combined Coverage Lines: 10.0 % 291 29
Test Date: 2025-08-26 15:45:50 Functions: 26.3 % 19 5

            Line data    Source code
       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              : 
      16            0 : static int is_ignored(int sig)
      17              : {
      18            0 :         return (sigismember(&current->blocked, sig) ||
      19            0 :                 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              :  */
      33           12 : int __tty_check_change(struct tty_struct *tty, int sig)
      34              : {
      35           12 :         unsigned long flags;
      36           12 :         struct pid *pgrp, *tty_pgrp;
      37           12 :         int ret = 0;
      38              : 
      39           12 :         if (current->signal->tty != tty)
      40           12 :                 return 0;
      41              : 
      42            0 :         rcu_read_lock();
      43            0 :         pgrp = task_pgrp(current);
      44              : 
      45            0 :         spin_lock_irqsave(&tty->ctrl.lock, flags);
      46            0 :         tty_pgrp = tty->ctrl.pgrp;
      47            0 :         spin_unlock_irqrestore(&tty->ctrl.lock, flags);
      48              : 
      49            0 :         if (tty_pgrp && pgrp != tty_pgrp) {
      50            0 :                 if (is_ignored(sig)) {
      51            0 :                         if (sig == SIGTTIN)
      52            0 :                                 ret = -EIO;
      53            0 :                 } else if (is_current_pgrp_orphaned())
      54            0 :                         ret = -EIO;
      55              :                 else {
      56            0 :                         kill_pgrp(pgrp, sig, 1);
      57            0 :                         set_thread_flag(TIF_SIGPENDING);
      58            0 :                         ret = -ERESTARTSYS;
      59              :                 }
      60            0 :         }
      61            0 :         rcu_read_unlock();
      62              : 
      63            0 :         if (!tty_pgrp)
      64            0 :                 tty_warn(tty, "sig=%d, tty->pgrp == NULL!\n", sig);
      65              : 
      66            0 :         return ret;
      67           12 : }
      68              : 
      69            0 : int tty_check_change(struct tty_struct *tty)
      70              : {
      71            0 :         return __tty_check_change(tty, SIGTTOU);
      72              : }
      73              : EXPORT_SYMBOL(tty_check_change);
      74              : 
      75            0 : void proc_clear_tty(struct task_struct *p)
      76              : {
      77            0 :         unsigned long flags;
      78            0 :         struct tty_struct *tty;
      79              : 
      80            0 :         spin_lock_irqsave(&p->sighand->siglock, flags);
      81            0 :         tty = p->signal->tty;
      82            0 :         p->signal->tty = NULL;
      83            0 :         spin_unlock_irqrestore(&p->sighand->siglock, flags);
      84            0 :         tty_kref_put(tty);
      85            0 : }
      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              :  */
      98            0 : static void __proc_set_tty(struct tty_struct *tty)
      99              : {
     100            0 :         unsigned long flags;
     101              : 
     102            0 :         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            0 :         put_pid(tty->ctrl.session);
     108            0 :         put_pid(tty->ctrl.pgrp);
     109            0 :         tty->ctrl.pgrp = get_pid(task_pgrp(current));
     110            0 :         tty->ctrl.session = get_pid(task_session(current));
     111            0 :         spin_unlock_irqrestore(&tty->ctrl.lock, flags);
     112            0 :         if (current->signal->tty) {
     113            0 :                 tty_debug(tty, "current tty %s not NULL!!\n",
     114              :                           current->signal->tty->name);
     115            0 :                 tty_kref_put(current->signal->tty);
     116            0 :         }
     117            0 :         put_pid(current->signal->tty_old_pgrp);
     118            0 :         current->signal->tty = tty_kref_get(tty);
     119            0 :         current->signal->tty_old_pgrp = NULL;
     120            0 : }
     121              : 
     122            0 : static void proc_set_tty(struct tty_struct *tty)
     123              : {
     124            0 :         spin_lock_irq(&current->sighand->siglock);
     125            0 :         __proc_set_tty(tty);
     126            0 :         spin_unlock_irq(&current->sighand->siglock);
     127            0 : }
     128              : 
     129              : /*
     130              :  * Called by tty_open() to set the controlling tty if applicable.
     131              :  */
     132            6 : void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty)
     133              : {
     134            6 :         read_lock(&tasklist_lock);
     135            6 :         spin_lock_irq(&current->sighand->siglock);
     136            6 :         if (current->signal->leader &&
     137            0 :             !current->signal->tty &&
     138            0 :             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            0 :                 if (filp->f_mode & FMODE_READ)
     154            0 :                         __proc_set_tty(tty);
     155            0 :         }
     156            6 :         spin_unlock_irq(&current->sighand->siglock);
     157            6 :         read_unlock(&tasklist_lock);
     158            6 : }
     159              : 
     160            0 : struct tty_struct *get_current_tty(void)
     161              : {
     162            0 :         struct tty_struct *tty;
     163            0 :         unsigned long flags;
     164              : 
     165            0 :         spin_lock_irqsave(&current->sighand->siglock, flags);
     166            0 :         tty = tty_kref_get(current->signal->tty);
     167            0 :         spin_unlock_irqrestore(&current->sighand->siglock, flags);
     168            0 :         return tty;
     169            0 : }
     170              : EXPORT_SYMBOL_GPL(get_current_tty);
     171              : 
     172              : /*
     173              :  * Called from tty_release().
     174              :  */
     175            6 : void session_clear_tty(struct pid *session)
     176              : {
     177            6 :         struct task_struct *p;
     178              : 
     179            6 :         do_each_pid_task(session, PIDTYPE_SID, p) {
     180            0 :                 proc_clear_tty(p);
     181            6 :         } while_each_pid_task(session, PIDTYPE_SID, p);
     182            6 : }
     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              :  */
     196            0 : int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
     197              : {
     198            0 :         struct task_struct *p;
     199            0 :         int refs = 0;
     200            0 :         struct pid *tty_pgrp = NULL;
     201              : 
     202            0 :         read_lock(&tasklist_lock);
     203            0 :         if (tty->ctrl.session) {
     204            0 :                 do_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p) {
     205            0 :                         spin_lock_irq(&p->sighand->siglock);
     206            0 :                         if (p->signal->tty == tty) {
     207            0 :                                 p->signal->tty = NULL;
     208              :                                 /*
     209              :                                  * We defer the dereferences outside of
     210              :                                  * the tasklist lock.
     211              :                                  */
     212            0 :                                 refs++;
     213            0 :                         }
     214            0 :                         if (!p->signal->leader) {
     215            0 :                                 spin_unlock_irq(&p->sighand->siglock);
     216            0 :                                 continue;
     217              :                         }
     218            0 :                         send_signal_locked(SIGHUP, SEND_SIG_PRIV, p, PIDTYPE_TGID);
     219            0 :                         send_signal_locked(SIGCONT, SEND_SIG_PRIV, p, PIDTYPE_TGID);
     220            0 :                         put_pid(p->signal->tty_old_pgrp);  /* A noop */
     221            0 :                         spin_lock(&tty->ctrl.lock);
     222            0 :                         tty_pgrp = get_pid(tty->ctrl.pgrp);
     223            0 :                         if (tty->ctrl.pgrp)
     224            0 :                                 p->signal->tty_old_pgrp =
     225            0 :                                         get_pid(tty->ctrl.pgrp);
     226            0 :                         spin_unlock(&tty->ctrl.lock);
     227            0 :                         spin_unlock_irq(&p->sighand->siglock);
     228            0 :                 } while_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p);
     229            0 :         }
     230            0 :         read_unlock(&tasklist_lock);
     231              : 
     232            0 :         if (tty_pgrp) {
     233            0 :                 if (exit_session)
     234            0 :                         kill_pgrp(tty_pgrp, SIGHUP, exit_session);
     235            0 :                 put_pid(tty_pgrp);
     236            0 :         }
     237              : 
     238            0 :         return refs;
     239            0 : }
     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              :  */
     265           29 : void disassociate_ctty(int on_exit)
     266              : {
     267           29 :         struct tty_struct *tty;
     268              : 
     269           29 :         if (!current->signal->leader)
     270           29 :                 return;
     271              : 
     272            0 :         tty = get_current_tty();
     273            0 :         if (tty) {
     274            0 :                 if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) {
     275            0 :                         tty_vhangup_session(tty);
     276            0 :                 } else {
     277            0 :                         struct pid *tty_pgrp = tty_get_pgrp(tty);
     278              : 
     279            0 :                         if (tty_pgrp) {
     280            0 :                                 kill_pgrp(tty_pgrp, SIGHUP, on_exit);
     281            0 :                                 if (!on_exit)
     282            0 :                                         kill_pgrp(tty_pgrp, SIGCONT, on_exit);
     283            0 :                                 put_pid(tty_pgrp);
     284            0 :                         }
     285            0 :                 }
     286            0 :                 tty_kref_put(tty);
     287              : 
     288            0 :         } else if (on_exit) {
     289            0 :                 struct pid *old_pgrp;
     290              : 
     291            0 :                 spin_lock_irq(&current->sighand->siglock);
     292            0 :                 old_pgrp = current->signal->tty_old_pgrp;
     293            0 :                 current->signal->tty_old_pgrp = NULL;
     294            0 :                 spin_unlock_irq(&current->sighand->siglock);
     295            0 :                 if (old_pgrp) {
     296            0 :                         kill_pgrp(old_pgrp, SIGHUP, on_exit);
     297            0 :                         kill_pgrp(old_pgrp, SIGCONT, on_exit);
     298            0 :                         put_pid(old_pgrp);
     299            0 :                 }
     300              :                 return;
     301            0 :         }
     302              : 
     303            0 :         tty = get_current_tty();
     304            0 :         if (tty) {
     305            0 :                 unsigned long flags;
     306              : 
     307            0 :                 tty_lock(tty);
     308            0 :                 spin_lock_irqsave(&tty->ctrl.lock, flags);
     309            0 :                 put_pid(tty->ctrl.session);
     310            0 :                 put_pid(tty->ctrl.pgrp);
     311            0 :                 tty->ctrl.session = NULL;
     312            0 :                 tty->ctrl.pgrp = NULL;
     313            0 :                 spin_unlock_irqrestore(&tty->ctrl.lock, flags);
     314            0 :                 tty_unlock(tty);
     315            0 :                 tty_kref_put(tty);
     316            0 :         }
     317              : 
     318              :         /* If tty->ctrl.pgrp is not NULL, it may be assigned to
     319              :          * current->signal->tty_old_pgrp in a race condition, and
     320              :          * cause pid memleak. Release current->signal->tty_old_pgrp
     321              :          * after tty->ctrl.pgrp set to NULL.
     322              :          */
     323            0 :         spin_lock_irq(&current->sighand->siglock);
     324            0 :         put_pid(current->signal->tty_old_pgrp);
     325            0 :         current->signal->tty_old_pgrp = NULL;
     326            0 :         spin_unlock_irq(&current->sighand->siglock);
     327              : 
     328              :         /* Now clear signal->tty under the lock */
     329            0 :         read_lock(&tasklist_lock);
     330            0 :         session_clear_tty(task_session(current));
     331            0 :         read_unlock(&tasklist_lock);
     332           29 : }
     333              : 
     334              : /*
     335              :  *
     336              :  *      no_tty  - Ensure the current process does not have a controlling tty
     337              :  */
     338            0 : void no_tty(void)
     339              : {
     340              :         /*
     341              :          * FIXME: Review locking here. The tty_lock never covered any race
     342              :          * between a new association and proc_clear_tty but possibly we need
     343              :          * to protect against this anyway.
     344              :          */
     345            0 :         struct task_struct *tsk = current;
     346              : 
     347            0 :         disassociate_ctty(0);
     348            0 :         proc_clear_tty(tsk);
     349            0 : }
     350              : 
     351              : /**
     352              :  *      tiocsctty       -       set controlling tty
     353              :  *      @tty: tty structure
     354              :  *      @file: file structure used to check permissions
     355              :  *      @arg: user argument
     356              :  *
     357              :  *      This ioctl is used to manage job control. It permits a session
     358              :  *      leader to set this tty as the controlling tty for the session.
     359              :  *
     360              :  *      Locking:
     361              :  *              Takes tty_lock() to serialize proc_set_tty() for this tty
     362              :  *              Takes tasklist_lock internally to walk sessions
     363              :  *              Takes ->siglock() when updating signal->tty
     364              :  */
     365            0 : static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
     366              : {
     367            0 :         int ret = 0;
     368              : 
     369            0 :         tty_lock(tty);
     370            0 :         read_lock(&tasklist_lock);
     371              : 
     372            0 :         if (current->signal->leader &&
     373            0 :                         task_session(current) == tty->ctrl.session)
     374            0 :                 goto unlock;
     375              : 
     376              :         /*
     377              :          * The process must be a session leader and
     378              :          * not have a controlling tty already.
     379              :          */
     380            0 :         if (!current->signal->leader || current->signal->tty) {
     381            0 :                 ret = -EPERM;
     382            0 :                 goto unlock;
     383              :         }
     384              : 
     385            0 :         if (tty->ctrl.session) {
     386              :                 /*
     387              :                  * This tty is already the controlling
     388              :                  * tty for another session group!
     389              :                  */
     390            0 :                 if (arg == 1 && capable(CAP_SYS_ADMIN)) {
     391              :                         /*
     392              :                          * Steal it away
     393              :                          */
     394            0 :                         session_clear_tty(tty->ctrl.session);
     395            0 :                 } else {
     396            0 :                         ret = -EPERM;
     397            0 :                         goto unlock;
     398              :                 }
     399            0 :         }
     400              : 
     401              :         /* See the comment in tty_open_proc_set_tty(). */
     402            0 :         if ((file->f_mode & FMODE_READ) == 0 && !capable(CAP_SYS_ADMIN)) {
     403            0 :                 ret = -EPERM;
     404            0 :                 goto unlock;
     405              :         }
     406              : 
     407            0 :         proc_set_tty(tty);
     408              : unlock:
     409            0 :         read_unlock(&tasklist_lock);
     410            0 :         tty_unlock(tty);
     411            0 :         return ret;
     412            0 : }
     413              : 
     414              : /**
     415              :  *      tty_get_pgrp    -       return a ref counted pgrp pid
     416              :  *      @tty: tty to read
     417              :  *
     418              :  *      Returns a refcounted instance of the pid struct for the process
     419              :  *      group controlling the tty.
     420              :  */
     421            0 : struct pid *tty_get_pgrp(struct tty_struct *tty)
     422              : {
     423            0 :         unsigned long flags;
     424            0 :         struct pid *pgrp;
     425              : 
     426            0 :         spin_lock_irqsave(&tty->ctrl.lock, flags);
     427            0 :         pgrp = get_pid(tty->ctrl.pgrp);
     428            0 :         spin_unlock_irqrestore(&tty->ctrl.lock, flags);
     429              : 
     430            0 :         return pgrp;
     431            0 : }
     432              : EXPORT_SYMBOL_GPL(tty_get_pgrp);
     433              : 
     434              : /*
     435              :  * This checks not only the pgrp, but falls back on the pid if no
     436              :  * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
     437              :  * without this...
     438              :  *
     439              :  * The caller must hold rcu lock or the tasklist lock.
     440              :  */
     441            0 : static struct pid *session_of_pgrp(struct pid *pgrp)
     442              : {
     443            0 :         struct task_struct *p;
     444            0 :         struct pid *sid = NULL;
     445              : 
     446            0 :         p = pid_task(pgrp, PIDTYPE_PGID);
     447            0 :         if (p == NULL)
     448            0 :                 p = pid_task(pgrp, PIDTYPE_PID);
     449            0 :         if (p != NULL)
     450            0 :                 sid = task_session(p);
     451              : 
     452            0 :         return sid;
     453            0 : }
     454              : 
     455              : /**
     456              :  *      tiocgpgrp               -       get process group
     457              :  *      @tty: tty passed by user
     458              :  *      @real_tty: tty side of the tty passed by the user if a pty else the tty
     459              :  *      @p: returned pid
     460              :  *
     461              :  *      Obtain the process group of the tty. If there is no process group
     462              :  *      return an error.
     463              :  *
     464              :  *      Locking: none. Reference to current->signal->tty is safe.
     465              :  */
     466            0 : static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
     467              : {
     468            0 :         struct pid *pid;
     469            0 :         int ret;
     470              :         /*
     471              :          * (tty == real_tty) is a cheap way of
     472              :          * testing if the tty is NOT a master pty.
     473              :          */
     474            0 :         if (tty == real_tty && current->signal->tty != real_tty)
     475            0 :                 return -ENOTTY;
     476            0 :         pid = tty_get_pgrp(real_tty);
     477            0 :         ret =  put_user(pid_vnr(pid), p);
     478            0 :         put_pid(pid);
     479            0 :         return ret;
     480            0 : }
     481              : 
     482              : /**
     483              :  *      tiocspgrp               -       attempt to set process group
     484              :  *      @tty: tty passed by user
     485              :  *      @real_tty: tty side device matching tty passed by user
     486              :  *      @p: pid pointer
     487              :  *
     488              :  *      Set the process group of the tty to the session passed. Only
     489              :  *      permitted where the tty session is our session.
     490              :  *
     491              :  *      Locking: RCU, ctrl lock
     492              :  */
     493            0 : static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
     494              : {
     495            0 :         struct pid *pgrp;
     496            0 :         pid_t pgrp_nr;
     497            0 :         int retval = tty_check_change(real_tty);
     498              : 
     499            0 :         if (retval == -EIO)
     500            0 :                 return -ENOTTY;
     501            0 :         if (retval)
     502            0 :                 return retval;
     503              : 
     504            0 :         if (get_user(pgrp_nr, p))
     505            0 :                 return -EFAULT;
     506            0 :         if (pgrp_nr < 0)
     507            0 :                 return -EINVAL;
     508              : 
     509            0 :         spin_lock_irq(&real_tty->ctrl.lock);
     510            0 :         if (!current->signal->tty ||
     511            0 :             (current->signal->tty != real_tty) ||
     512            0 :             (real_tty->ctrl.session != task_session(current))) {
     513            0 :                 retval = -ENOTTY;
     514            0 :                 goto out_unlock_ctrl;
     515              :         }
     516            0 :         rcu_read_lock();
     517            0 :         pgrp = find_vpid(pgrp_nr);
     518            0 :         retval = -ESRCH;
     519            0 :         if (!pgrp)
     520            0 :                 goto out_unlock;
     521            0 :         retval = -EPERM;
     522            0 :         if (session_of_pgrp(pgrp) != task_session(current))
     523            0 :                 goto out_unlock;
     524            0 :         retval = 0;
     525            0 :         put_pid(real_tty->ctrl.pgrp);
     526            0 :         real_tty->ctrl.pgrp = get_pid(pgrp);
     527              : out_unlock:
     528            0 :         rcu_read_unlock();
     529              : out_unlock_ctrl:
     530            0 :         spin_unlock_irq(&real_tty->ctrl.lock);
     531            0 :         return retval;
     532            0 : }
     533              : 
     534              : /**
     535              :  *      tiocgsid                -       get session id
     536              :  *      @tty: tty passed by user
     537              :  *      @real_tty: tty side of the tty passed by the user if a pty else the tty
     538              :  *      @p: pointer to returned session id
     539              :  *
     540              :  *      Obtain the session id of the tty. If there is no session
     541              :  *      return an error.
     542              :  */
     543            0 : static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
     544              : {
     545            0 :         unsigned long flags;
     546            0 :         pid_t sid;
     547              : 
     548              :         /*
     549              :          * (tty == real_tty) is a cheap way of
     550              :          * testing if the tty is NOT a master pty.
     551              :          */
     552            0 :         if (tty == real_tty && current->signal->tty != real_tty)
     553            0 :                 return -ENOTTY;
     554              : 
     555            0 :         spin_lock_irqsave(&real_tty->ctrl.lock, flags);
     556            0 :         if (!real_tty->ctrl.session)
     557            0 :                 goto err;
     558            0 :         sid = pid_vnr(real_tty->ctrl.session);
     559            0 :         spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
     560              : 
     561            0 :         return put_user(sid, p);
     562              : 
     563              : err:
     564            0 :         spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
     565            0 :         return -ENOTTY;
     566            0 : }
     567              : 
     568              : /*
     569              :  * Called from tty_ioctl(). If tty is a pty then real_tty is the slave side,
     570              :  * if not then tty == real_tty.
     571              :  */
     572           18 : long tty_jobctrl_ioctl(struct tty_struct *tty, struct tty_struct *real_tty,
     573              :                        struct file *file, unsigned int cmd, unsigned long arg)
     574              : {
     575           18 :         void __user *p = (void __user *)arg;
     576              : 
     577           18 :         switch (cmd) {
     578              :         case TIOCNOTTY:
     579            0 :                 if (current->signal->tty != tty)
     580            0 :                         return -ENOTTY;
     581            0 :                 no_tty();
     582            0 :                 return 0;
     583              :         case TIOCSCTTY:
     584            0 :                 return tiocsctty(real_tty, file, arg);
     585              :         case TIOCGPGRP:
     586            0 :                 return tiocgpgrp(tty, real_tty, p);
     587              :         case TIOCSPGRP:
     588            0 :                 return tiocspgrp(tty, real_tty, p);
     589              :         case TIOCGSID:
     590            0 :                 return tiocgsid(tty, real_tty, p);
     591              :         }
     592           18 :         return -ENOIOCTLCMD;
     593           18 : }
        

Generated by: LCOV version 2.0-1