LCOV - code coverage report
Current view: top level - drivers/tty - tty_jobctrl.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 209 1.0 %
Date: 2023-03-27 20:00:47 Functions: 1 17 5.9 %

          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             : 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           0 : int __tty_check_change(struct tty_struct *tty, int sig)
      34             : {
      35             :         unsigned long flags;
      36             :         struct pid *pgrp, *tty_pgrp;
      37           0 :         int ret = 0;
      38             : 
      39           0 :         if (current->signal->tty != tty)
      40             :                 return 0;
      41             : 
      42             :         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             :                         ret = -EIO;
      55             :                 else {
      56           0 :                         kill_pgrp(pgrp, sig, 1);
      57           0 :                         set_thread_flag(TIF_SIGPENDING);
      58           0 :                         ret = -ERESTARTSYS;
      59             :                 }
      60             :         }
      61             :         rcu_read_unlock();
      62             : 
      63           0 :         if (!tty_pgrp)
      64           0 :                 tty_warn(tty, "sig=%d, tty->pgrp == NULL!\n", sig);
      65             : 
      66             :         return ret;
      67             : }
      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             :         unsigned long flags;
      78             :         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             :         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             :                 tty_debug(tty, "current tty %s not NULL!!\n",
     114             :                           current->signal->tty->name);
     115           0 :                 tty_kref_put(current->signal->tty);
     116             :         }
     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             : 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             : }
     128             : 
     129             : /*
     130             :  * Called by tty_open() to set the controlling tty if applicable.
     131             :  */
     132           0 : void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty)
     133             : {
     134           0 :         read_lock(&tasklist_lock);
     135           0 :         spin_lock_irq(&current->sighand->siglock);
     136           0 :         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             :         }
     156           0 :         spin_unlock_irq(&current->sighand->siglock);
     157           0 :         read_unlock(&tasklist_lock);
     158           0 : }
     159             : 
     160           0 : struct tty_struct *get_current_tty(void)
     161             : {
     162             :         struct tty_struct *tty;
     163             :         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             : }
     170             : EXPORT_SYMBOL_GPL(get_current_tty);
     171             : 
     172             : /*
     173             :  * Called from tty_release().
     174             :  */
     175           0 : void session_clear_tty(struct pid *session)
     176             : {
     177             :         struct task_struct *p;
     178             : 
     179           0 :         do_each_pid_task(session, PIDTYPE_SID, p) {
     180           0 :                 proc_clear_tty(p);
     181             :         } while_each_pid_task(session, PIDTYPE_SID, p);
     182           0 : }
     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             :         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             :                         }
     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             :                 } while_each_pid_task(tty->ctrl.session, PIDTYPE_SID, p);
     229             :         }
     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             :         }
     237             : 
     238           0 :         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             :  */
     265         325 : void disassociate_ctty(int on_exit)
     266             : {
     267             :         struct tty_struct *tty;
     268             : 
     269         325 :         if (!current->signal->leader)
     270             :                 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             :                 } 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             :                         }
     285             :                 }
     286           0 :                 tty_kref_put(tty);
     287             : 
     288           0 :         } else if (on_exit) {
     289             :                 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             :                 }
     300             :                 return;
     301             :         }
     302             : 
     303           0 :         spin_lock_irq(&current->sighand->siglock);
     304           0 :         put_pid(current->signal->tty_old_pgrp);
     305           0 :         current->signal->tty_old_pgrp = NULL;
     306           0 :         tty = tty_kref_get(current->signal->tty);
     307           0 :         spin_unlock_irq(&current->sighand->siglock);
     308             : 
     309           0 :         if (tty) {
     310             :                 unsigned long flags;
     311             : 
     312           0 :                 tty_lock(tty);
     313           0 :                 spin_lock_irqsave(&tty->ctrl.lock, flags);
     314           0 :                 put_pid(tty->ctrl.session);
     315           0 :                 put_pid(tty->ctrl.pgrp);
     316           0 :                 tty->ctrl.session = NULL;
     317           0 :                 tty->ctrl.pgrp = NULL;
     318           0 :                 spin_unlock_irqrestore(&tty->ctrl.lock, flags);
     319           0 :                 tty_unlock(tty);
     320           0 :                 tty_kref_put(tty);
     321             :         }
     322             : 
     323             :         /* Now clear signal->tty under the lock */
     324           0 :         read_lock(&tasklist_lock);
     325           0 :         session_clear_tty(task_session(current));
     326           0 :         read_unlock(&tasklist_lock);
     327             : }
     328             : 
     329             : /*
     330             :  *
     331             :  *      no_tty  - Ensure the current process does not have a controlling tty
     332             :  */
     333           0 : void 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           0 :         struct task_struct *tsk = current;
     341             : 
     342           0 :         disassociate_ctty(0);
     343           0 :         proc_clear_tty(tsk);
     344           0 : }
     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             :  */
     360           0 : static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
     361             : {
     362           0 :         int ret = 0;
     363             : 
     364           0 :         tty_lock(tty);
     365           0 :         read_lock(&tasklist_lock);
     366             : 
     367           0 :         if (current->signal->leader &&
     368           0 :                         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           0 :         if (!current->signal->leader || current->signal->tty) {
     376             :                 ret = -EPERM;
     377             :                 goto unlock;
     378             :         }
     379             : 
     380           0 :         if (tty->ctrl.session) {
     381             :                 /*
     382             :                  * This tty is already the controlling
     383             :                  * tty for another session group!
     384             :                  */
     385           0 :                 if (arg == 1 && capable(CAP_SYS_ADMIN)) {
     386             :                         /*
     387             :                          * Steal it away
     388             :                          */
     389           0 :                         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           0 :         if ((file->f_mode & FMODE_READ) == 0 && !capable(CAP_SYS_ADMIN)) {
     398             :                 ret = -EPERM;
     399             :                 goto unlock;
     400             :         }
     401             : 
     402             :         proc_set_tty(tty);
     403             : unlock:
     404           0 :         read_unlock(&tasklist_lock);
     405           0 :         tty_unlock(tty);
     406           0 :         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             :  */
     416           0 : struct pid *tty_get_pgrp(struct tty_struct *tty)
     417             : {
     418             :         unsigned long flags;
     419             :         struct pid *pgrp;
     420             : 
     421           0 :         spin_lock_irqsave(&tty->ctrl.lock, flags);
     422           0 :         pgrp = get_pid(tty->ctrl.pgrp);
     423           0 :         spin_unlock_irqrestore(&tty->ctrl.lock, flags);
     424             : 
     425           0 :         return pgrp;
     426             : }
     427             : EXPORT_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             :  */
     436           0 : static struct pid *session_of_pgrp(struct pid *pgrp)
     437             : {
     438             :         struct task_struct *p;
     439           0 :         struct pid *sid = NULL;
     440             : 
     441           0 :         p = pid_task(pgrp, PIDTYPE_PGID);
     442           0 :         if (p == NULL)
     443           0 :                 p = pid_task(pgrp, PIDTYPE_PID);
     444           0 :         if (p != NULL)
     445           0 :                 sid = task_session(p);
     446             : 
     447           0 :         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             :  */
     461           0 : static 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           0 :         if (tty == real_tty && current->signal->tty != real_tty)
     470             :                 return -ENOTTY;
     471           0 :         pid = tty_get_pgrp(real_tty);
     472           0 :         ret =  put_user(pid_vnr(pid), p);
     473           0 :         put_pid(pid);
     474           0 :         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             :  */
     488           0 : static 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           0 :         int retval = tty_check_change(real_tty);
     493             : 
     494           0 :         if (retval == -EIO)
     495             :                 return -ENOTTY;
     496           0 :         if (retval)
     497             :                 return retval;
     498             : 
     499           0 :         if (get_user(pgrp_nr, p))
     500             :                 return -EFAULT;
     501           0 :         if (pgrp_nr < 0)
     502             :                 return -EINVAL;
     503             : 
     504           0 :         spin_lock_irq(&real_tty->ctrl.lock);
     505           0 :         if (!current->signal->tty ||
     506           0 :             (current->signal->tty != real_tty) ||
     507           0 :             (real_tty->ctrl.session != task_session(current))) {
     508             :                 retval = -ENOTTY;
     509             :                 goto out_unlock_ctrl;
     510             :         }
     511             :         rcu_read_lock();
     512           0 :         pgrp = find_vpid(pgrp_nr);
     513           0 :         retval = -ESRCH;
     514           0 :         if (!pgrp)
     515             :                 goto out_unlock;
     516           0 :         retval = -EPERM;
     517           0 :         if (session_of_pgrp(pgrp) != task_session(current))
     518             :                 goto out_unlock;
     519           0 :         retval = 0;
     520           0 :         put_pid(real_tty->ctrl.pgrp);
     521           0 :         real_tty->ctrl.pgrp = get_pid(pgrp);
     522             : out_unlock:
     523             :         rcu_read_unlock();
     524             : out_unlock_ctrl:
     525           0 :         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             :  */
     538           0 : static 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           0 :         if (tty == real_tty && current->signal->tty != real_tty)
     548             :                 return -ENOTTY;
     549             : 
     550           0 :         spin_lock_irqsave(&real_tty->ctrl.lock, flags);
     551           0 :         if (!real_tty->ctrl.session)
     552             :                 goto err;
     553           0 :         sid = pid_vnr(real_tty->ctrl.session);
     554           0 :         spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
     555             : 
     556           0 :         return put_user(sid, p);
     557             : 
     558             : err:
     559           0 :         spin_unlock_irqrestore(&real_tty->ctrl.lock, flags);
     560           0 :         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             :  */
     567           0 : long tty_jobctrl_ioctl(struct tty_struct *tty, struct tty_struct *real_tty,
     568             :                        struct file *file, unsigned int cmd, unsigned long arg)
     569             : {
     570           0 :         void __user *p = (void __user *)arg;
     571             : 
     572           0 :         switch (cmd) {
     573             :         case TIOCNOTTY:
     574           0 :                 if (current->signal->tty != tty)
     575             :                         return -ENOTTY;
     576           0 :                 no_tty();
     577           0 :                 return 0;
     578             :         case TIOCSCTTY:
     579           0 :                 return tiocsctty(real_tty, file, arg);
     580             :         case TIOCGPGRP:
     581           0 :                 return tiocgpgrp(tty, real_tty, p);
     582             :         case TIOCSPGRP:
     583           0 :                 return tiocspgrp(tty, real_tty, p);
     584             :         case TIOCGSID:
     585           0 :                 return tiocgsid(tty, real_tty, p);
     586             :         }
     587             :         return -ENOIOCTLCMD;
     588             : }

Generated by: LCOV version 1.14