LCOV - code coverage report
Current view: top level - tty/vt - vt_ioctl.c (source / functions) Coverage Total Hit
Test: TTY Combined Coverage Lines: 0.0 % 618 0
Test Date: 2025-08-26 15:45:50 Functions: 0.0 % 28 0

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0
       2              : /*
       3              :  *  Copyright (C) 1992 obz under the linux copyright
       4              :  *
       5              :  *  Dynamic diacritical handling - [email protected] - Dec 1993
       6              :  *  Dynamic keymap and string allocation - [email protected] - May 1994
       7              :  *  Restrict VT switching via ioctl() - [email protected] - Dec 1995
       8              :  *  Some code moved for less code duplication - Andi Kleen - Mar 1997
       9              :  *  Check put/get_user, cleanups - [email protected] - Jun 2001
      10              :  */
      11              : 
      12              : #include <linux/types.h>
      13              : #include <linux/errno.h>
      14              : #include <linux/sched/signal.h>
      15              : #include <linux/tty.h>
      16              : #include <linux/timer.h>
      17              : #include <linux/kernel.h>
      18              : #include <linux/compat.h>
      19              : #include <linux/module.h>
      20              : #include <linux/kd.h>
      21              : #include <linux/vt.h>
      22              : #include <linux/string.h>
      23              : #include <linux/slab.h>
      24              : #include <linux/major.h>
      25              : #include <linux/fs.h>
      26              : #include <linux/console.h>
      27              : #include <linux/consolemap.h>
      28              : #include <linux/signal.h>
      29              : #include <linux/suspend.h>
      30              : #include <linux/timex.h>
      31              : 
      32              : #include <asm/io.h>
      33              : #include <linux/uaccess.h>
      34              : 
      35              : #include <linux/nospec.h>
      36              : 
      37              : #include <linux/kbd_kern.h>
      38              : #include <linux/vt_kern.h>
      39              : #include <linux/kbd_diacr.h>
      40              : #include <linux/selection.h>
      41              : 
      42              : bool vt_dont_switch;
      43              : 
      44            0 : static inline bool vt_in_use(unsigned int i)
      45              : {
      46            0 :         const struct vc_data *vc = vc_cons[i].d;
      47              : 
      48              :         /*
      49              :          * console_lock must be held to prevent the vc from being deallocated
      50              :          * while we're checking whether it's in-use.
      51              :          */
      52            0 :         WARN_CONSOLE_UNLOCKED();
      53              : 
      54            0 :         return vc && kref_read(&vc->port.kref) > 1;
      55            0 : }
      56              : 
      57            0 : static inline bool vt_busy(int i)
      58              : {
      59            0 :         if (vt_in_use(i))
      60            0 :                 return true;
      61            0 :         if (i == fg_console)
      62            0 :                 return true;
      63            0 :         if (vc_is_sel(vc_cons[i].d))
      64            0 :                 return true;
      65              : 
      66            0 :         return false;
      67            0 : }
      68              : 
      69              : /*
      70              :  * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
      71              :  * experimentation and study of X386 SYSV handling.
      72              :  *
      73              :  * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
      74              :  * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
      75              :  * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
      76              :  * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
      77              :  * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
      78              :  * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
      79              :  * to the current console is done by the main ioctl code.
      80              :  */
      81              : 
      82              : #ifdef CONFIG_X86
      83              : #include <asm/syscalls.h>
      84              : #endif
      85              : 
      86              : static void complete_change_console(struct vc_data *vc);
      87              : 
      88              : /*
      89              :  *      User space VT_EVENT handlers
      90              :  */
      91              : 
      92              : struct vt_event_wait {
      93              :         struct list_head list;
      94              :         struct vt_event event;
      95              :         int done;
      96              : };
      97              : 
      98              : static LIST_HEAD(vt_events);
      99              : static DEFINE_SPINLOCK(vt_event_lock);
     100              : static DECLARE_WAIT_QUEUE_HEAD(vt_event_waitqueue);
     101              : 
     102              : /**
     103              :  *      vt_event_post
     104              :  *      @event: the event that occurred
     105              :  *      @old: old console
     106              :  *      @new: new console
     107              :  *
     108              :  *      Post an VT event to interested VT handlers
     109              :  */
     110              : 
     111            0 : void vt_event_post(unsigned int event, unsigned int old, unsigned int new)
     112              : {
     113            0 :         struct list_head *pos, *head;
     114            0 :         unsigned long flags;
     115            0 :         int wake = 0;
     116              : 
     117            0 :         spin_lock_irqsave(&vt_event_lock, flags);
     118            0 :         head = &vt_events;
     119              : 
     120            0 :         list_for_each(pos, head) {
     121            0 :                 struct vt_event_wait *ve = list_entry(pos,
     122              :                                                 struct vt_event_wait, list);
     123            0 :                 if (!(ve->event.event & event))
     124            0 :                         continue;
     125            0 :                 ve->event.event = event;
     126              :                 /* kernel view is consoles 0..n-1, user space view is
     127              :                    console 1..n with 0 meaning current, so we must bias */
     128            0 :                 ve->event.oldev = old + 1;
     129            0 :                 ve->event.newev = new + 1;
     130            0 :                 wake = 1;
     131            0 :                 ve->done = 1;
     132            0 :         }
     133            0 :         spin_unlock_irqrestore(&vt_event_lock, flags);
     134            0 :         if (wake)
     135            0 :                 wake_up_interruptible(&vt_event_waitqueue);
     136            0 : }
     137              : 
     138            0 : static void __vt_event_queue(struct vt_event_wait *vw)
     139              : {
     140            0 :         unsigned long flags;
     141              :         /* Prepare the event */
     142            0 :         INIT_LIST_HEAD(&vw->list);
     143            0 :         vw->done = 0;
     144              :         /* Queue our event */
     145            0 :         spin_lock_irqsave(&vt_event_lock, flags);
     146            0 :         list_add(&vw->list, &vt_events);
     147            0 :         spin_unlock_irqrestore(&vt_event_lock, flags);
     148            0 : }
     149              : 
     150            0 : static void __vt_event_wait(struct vt_event_wait *vw)
     151              : {
     152              :         /* Wait for it to pass */
     153            0 :         wait_event_interruptible(vt_event_waitqueue, vw->done);
     154            0 : }
     155              : 
     156            0 : static void __vt_event_dequeue(struct vt_event_wait *vw)
     157              : {
     158            0 :         unsigned long flags;
     159              : 
     160              :         /* Dequeue it */
     161            0 :         spin_lock_irqsave(&vt_event_lock, flags);
     162            0 :         list_del(&vw->list);
     163            0 :         spin_unlock_irqrestore(&vt_event_lock, flags);
     164            0 : }
     165              : 
     166              : /**
     167              :  *      vt_event_wait           -       wait for an event
     168              :  *      @vw: our event
     169              :  *
     170              :  *      Waits for an event to occur which completes our vt_event_wait
     171              :  *      structure. On return the structure has wv->done set to 1 for success
     172              :  *      or 0 if some event such as a signal ended the wait.
     173              :  */
     174              : 
     175            0 : static void vt_event_wait(struct vt_event_wait *vw)
     176              : {
     177            0 :         __vt_event_queue(vw);
     178            0 :         __vt_event_wait(vw);
     179            0 :         __vt_event_dequeue(vw);
     180            0 : }
     181              : 
     182              : /**
     183              :  *      vt_event_wait_ioctl     -       event ioctl handler
     184              :  *      @event: argument to ioctl (the event)
     185              :  *
     186              :  *      Implement the VT_WAITEVENT ioctl using the VT event interface
     187              :  */
     188              : 
     189            0 : static int vt_event_wait_ioctl(struct vt_event __user *event)
     190              : {
     191            0 :         struct vt_event_wait vw;
     192              : 
     193            0 :         if (copy_from_user(&vw.event, event, sizeof(struct vt_event)))
     194            0 :                 return -EFAULT;
     195              :         /* Highest supported event for now */
     196            0 :         if (vw.event.event & ~VT_MAX_EVENT)
     197            0 :                 return -EINVAL;
     198              : 
     199            0 :         vt_event_wait(&vw);
     200              :         /* If it occurred report it */
     201            0 :         if (vw.done) {
     202            0 :                 if (copy_to_user(event, &vw.event, sizeof(struct vt_event)))
     203            0 :                         return -EFAULT;
     204            0 :                 return 0;
     205              :         }
     206            0 :         return -EINTR;
     207            0 : }
     208              : 
     209              : /**
     210              :  *      vt_waitactive   -       active console wait
     211              :  *      @n: new console
     212              :  *
     213              :  *      Helper for event waits. Used to implement the legacy
     214              :  *      event waiting ioctls in terms of events
     215              :  */
     216              : 
     217            0 : int vt_waitactive(int n)
     218              : {
     219            0 :         struct vt_event_wait vw;
     220            0 :         do {
     221            0 :                 vw.event.event = VT_EVENT_SWITCH;
     222            0 :                 __vt_event_queue(&vw);
     223            0 :                 if (n == fg_console + 1) {
     224            0 :                         __vt_event_dequeue(&vw);
     225            0 :                         break;
     226              :                 }
     227            0 :                 __vt_event_wait(&vw);
     228            0 :                 __vt_event_dequeue(&vw);
     229            0 :                 if (vw.done == 0)
     230            0 :                         return -EINTR;
     231            0 :         } while (vw.event.newev != n);
     232            0 :         return 0;
     233            0 : }
     234              : 
     235              : /*
     236              :  * these are the valid i/o ports we're allowed to change. they map all the
     237              :  * video ports
     238              :  */
     239              : #define GPFIRST 0x3b4
     240              : #define GPLAST 0x3df
     241              : #define GPNUM (GPLAST - GPFIRST + 1)
     242              : 
     243              : /*
     244              :  * currently, setting the mode from KD_TEXT to KD_GRAPHICS doesn't do a whole
     245              :  * lot. i'm not sure if it should do any restoration of modes or what...
     246              :  *
     247              :  * XXX It should at least call into the driver, fbdev's definitely need to
     248              :  * restore their engine state. --BenH
     249              :  *
     250              :  * Called with the console lock held.
     251              :  */
     252            0 : static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
     253              : {
     254            0 :         switch (mode) {
     255              :         case KD_GRAPHICS:
     256            0 :                 break;
     257              :         case KD_TEXT0:
     258              :         case KD_TEXT1:
     259            0 :                 mode = KD_TEXT;
     260              :                 fallthrough;
     261              :         case KD_TEXT:
     262            0 :                 break;
     263              :         default:
     264            0 :                 return -EINVAL;
     265              :         }
     266              : 
     267            0 :         if (vc->vc_mode == mode)
     268            0 :                 return 0;
     269              : 
     270            0 :         vc->vc_mode = mode;
     271            0 :         if (vc->vc_num != fg_console)
     272            0 :                 return 0;
     273              : 
     274              :         /* explicitly blank/unblank the screen if switching modes */
     275            0 :         if (mode == KD_TEXT)
     276            0 :                 do_unblank_screen(1);
     277              :         else
     278            0 :                 do_blank_screen(1);
     279              : 
     280            0 :         return 0;
     281            0 : }
     282              : 
     283            0 : static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd,
     284              :                 unsigned long arg, bool perm)
     285              : {
     286            0 :         struct vc_data *vc = tty->driver_data;
     287            0 :         void __user *up = (void __user *)arg;
     288            0 :         unsigned int console = vc->vc_num;
     289            0 :         int ret;
     290              : 
     291            0 :         switch (cmd) {
     292              :         case KIOCSOUND:
     293            0 :                 if (!perm)
     294            0 :                         return -EPERM;
     295              :                 /*
     296              :                  * The use of PIT_TICK_RATE is historic, it used to be
     297              :                  * the platform-dependent CLOCK_TICK_RATE between 2.6.12
     298              :                  * and 2.6.36, which was a minor but unfortunate ABI
     299              :                  * change. kd_mksound is locked by the input layer.
     300              :                  */
     301            0 :                 if (arg)
     302            0 :                         arg = PIT_TICK_RATE / arg;
     303            0 :                 kd_mksound(arg, 0);
     304            0 :                 break;
     305              : 
     306              :         case KDMKTONE:
     307            0 :                 if (!perm)
     308            0 :                         return -EPERM;
     309              :         {
     310            0 :                 unsigned int ticks, count;
     311              : 
     312              :                 /*
     313              :                  * Generate the tone for the appropriate number of ticks.
     314              :                  * If the time is zero, turn off sound ourselves.
     315              :                  */
     316            0 :                 ticks = msecs_to_jiffies((arg >> 16) & 0xffff);
     317            0 :                 count = ticks ? (arg & 0xffff) : 0;
     318            0 :                 if (count)
     319            0 :                         count = PIT_TICK_RATE / count;
     320            0 :                 kd_mksound(count, ticks);
     321              :                 break;
     322            0 :         }
     323              : 
     324              :         case KDGKBTYPE:
     325              :                 /*
     326              :                  * this is naïve.
     327              :                  */
     328            0 :                 return put_user(KB_101, (char __user *)arg);
     329              : 
     330              :                 /*
     331              :                  * These cannot be implemented on any machine that implements
     332              :                  * ioperm() in user level (such as Alpha PCs) or not at all.
     333              :                  *
     334              :                  * XXX: you should never use these, just call ioperm directly..
     335              :                  */
     336              : #ifdef CONFIG_X86
     337              :         case KDADDIO:
     338              :         case KDDELIO:
     339              :                 /*
     340              :                  * KDADDIO and KDDELIO may be able to add ports beyond what
     341              :                  * we reject here, but to be safe...
     342              :                  *
     343              :                  * These are locked internally via sys_ioperm
     344              :                  */
     345            0 :                 if (arg < GPFIRST || arg > GPLAST)
     346            0 :                         return -EINVAL;
     347              : 
     348            0 :                 return ksys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
     349              : 
     350              :         case KDENABIO:
     351              :         case KDDISABIO:
     352            0 :                 return ksys_ioperm(GPFIRST, GPNUM,
     353            0 :                                   (cmd == KDENABIO)) ? -ENXIO : 0;
     354              : #endif
     355              : 
     356              :         /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
     357              : 
     358              :         case KDKBDREP:
     359              :         {
     360            0 :                 struct kbd_repeat kbrep;
     361              : 
     362            0 :                 if (!capable(CAP_SYS_TTY_CONFIG))
     363            0 :                         return -EPERM;
     364              : 
     365            0 :                 if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat)))
     366            0 :                         return -EFAULT;
     367              : 
     368            0 :                 ret = kbd_rate(&kbrep);
     369            0 :                 if (ret)
     370            0 :                         return ret;
     371            0 :                 if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
     372            0 :                         return -EFAULT;
     373            0 :                 break;
     374            0 :         }
     375              : 
     376              :         case KDSETMODE:
     377            0 :                 if (!perm)
     378            0 :                         return -EPERM;
     379              : 
     380            0 :                 console_lock();
     381            0 :                 ret = vt_kdsetmode(vc, arg);
     382            0 :                 console_unlock();
     383            0 :                 return ret;
     384              : 
     385              :         case KDGETMODE:
     386            0 :                 return put_user(vc->vc_mode, (int __user *)arg);
     387              : 
     388              :         case KDMAPDISP:
     389              :         case KDUNMAPDISP:
     390              :                 /*
     391              :                  * these work like a combination of mmap and KDENABIO.
     392              :                  * this could be easily finished.
     393              :                  */
     394            0 :                 return -EINVAL;
     395              : 
     396              :         case KDSKBMODE:
     397            0 :                 if (!perm)
     398            0 :                         return -EPERM;
     399            0 :                 ret = vt_do_kdskbmode(console, arg);
     400            0 :                 if (ret)
     401            0 :                         return ret;
     402            0 :                 tty_ldisc_flush(tty);
     403            0 :                 break;
     404              : 
     405              :         case KDGKBMODE:
     406            0 :                 return put_user(vt_do_kdgkbmode(console), (int __user *)arg);
     407              : 
     408              :         /* this could be folded into KDSKBMODE, but for compatibility
     409              :            reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
     410              :         case KDSKBMETA:
     411            0 :                 return vt_do_kdskbmeta(console, arg);
     412              : 
     413              :         case KDGKBMETA:
     414              :                 /* FIXME: should review whether this is worth locking */
     415            0 :                 return put_user(vt_do_kdgkbmeta(console), (int __user *)arg);
     416              : 
     417              :         case KDGETKEYCODE:
     418              :         case KDSETKEYCODE:
     419            0 :                 if(!capable(CAP_SYS_TTY_CONFIG))
     420            0 :                         perm = 0;
     421            0 :                 return vt_do_kbkeycode_ioctl(cmd, up, perm);
     422              : 
     423              :         case KDGKBENT:
     424              :         case KDSKBENT:
     425            0 :                 return vt_do_kdsk_ioctl(cmd, up, perm, console);
     426              : 
     427              :         case KDGKBSENT:
     428              :         case KDSKBSENT:
     429            0 :                 return vt_do_kdgkb_ioctl(cmd, up, perm);
     430              : 
     431              :         /* Diacritical processing. Handled in keyboard.c as it has
     432              :            to operate on the keyboard locks and structures */
     433              :         case KDGKBDIACR:
     434              :         case KDGKBDIACRUC:
     435              :         case KDSKBDIACR:
     436              :         case KDSKBDIACRUC:
     437            0 :                 return vt_do_diacrit(cmd, up, perm);
     438              : 
     439              :         /* the ioctls below read/set the flags usually shown in the leds */
     440              :         /* don't use them - they will go away without warning */
     441              :         case KDGKBLED:
     442              :         case KDSKBLED:
     443              :         case KDGETLED:
     444              :         case KDSETLED:
     445            0 :                 return vt_do_kdskled(console, cmd, arg, perm);
     446              : 
     447              :         /*
     448              :          * A process can indicate its willingness to accept signals
     449              :          * generated by pressing an appropriate key combination.
     450              :          * Thus, one can have a daemon that e.g. spawns a new console
     451              :          * upon a keypress and then changes to it.
     452              :          * See also the kbrequest field of inittab(5).
     453              :          */
     454              :         case KDSIGACCEPT:
     455            0 :                 if (!perm || !capable(CAP_KILL))
     456            0 :                         return -EPERM;
     457            0 :                 if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
     458            0 :                         return -EINVAL;
     459              : 
     460            0 :                 spin_lock_irq(&vt_spawn_con.lock);
     461            0 :                 put_pid(vt_spawn_con.pid);
     462            0 :                 vt_spawn_con.pid = get_pid(task_pid(current));
     463            0 :                 vt_spawn_con.sig = arg;
     464            0 :                 spin_unlock_irq(&vt_spawn_con.lock);
     465            0 :                 break;
     466              : 
     467              :         case KDFONTOP: {
     468            0 :                 struct console_font_op op;
     469              : 
     470            0 :                 if (copy_from_user(&op, up, sizeof(op)))
     471            0 :                         return -EFAULT;
     472            0 :                 if (!perm && op.op != KD_FONT_OP_GET)
     473            0 :                         return -EPERM;
     474            0 :                 ret = con_font_op(vc, &op);
     475            0 :                 if (ret)
     476            0 :                         return ret;
     477            0 :                 if (copy_to_user(up, &op, sizeof(op)))
     478            0 :                         return -EFAULT;
     479            0 :                 break;
     480            0 :         }
     481              : 
     482              :         default:
     483            0 :                 return -ENOIOCTLCMD;
     484              :         }
     485              : 
     486            0 :         return 0;
     487            0 : }
     488              : 
     489            0 : static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
     490              :                 bool perm, struct vc_data *vc)
     491              : {
     492            0 :         struct unimapdesc tmp;
     493              : 
     494            0 :         if (copy_from_user(&tmp, user_ud, sizeof tmp))
     495            0 :                 return -EFAULT;
     496            0 :         switch (cmd) {
     497              :         case PIO_UNIMAP:
     498            0 :                 if (!perm)
     499            0 :                         return -EPERM;
     500            0 :                 return con_set_unimap(vc, tmp.entry_ct, tmp.entries);
     501              :         case GIO_UNIMAP:
     502            0 :                 if (!perm && fg_console != vc->vc_num)
     503            0 :                         return -EPERM;
     504            0 :                 return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
     505            0 :                                 tmp.entries);
     506              :         }
     507            0 :         return 0;
     508            0 : }
     509              : 
     510            0 : static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,
     511              :                 bool perm)
     512              : {
     513            0 :         switch (cmd) {
     514              :         case PIO_CMAP:
     515            0 :                 if (!perm)
     516            0 :                         return -EPERM;
     517            0 :                 return con_set_cmap(up);
     518              : 
     519              :         case GIO_CMAP:
     520            0 :                 return con_get_cmap(up);
     521              : 
     522              :         case PIO_SCRNMAP:
     523            0 :                 if (!perm)
     524            0 :                         return -EPERM;
     525            0 :                 return con_set_trans_old(up);
     526              : 
     527              :         case GIO_SCRNMAP:
     528            0 :                 return con_get_trans_old(up);
     529              : 
     530              :         case PIO_UNISCRNMAP:
     531            0 :                 if (!perm)
     532            0 :                         return -EPERM;
     533            0 :                 return con_set_trans_new(up);
     534              : 
     535              :         case GIO_UNISCRNMAP:
     536            0 :                 return con_get_trans_new(up);
     537              : 
     538              :         case PIO_UNIMAPCLR:
     539            0 :                 if (!perm)
     540            0 :                         return -EPERM;
     541            0 :                 con_clear_unimap(vc);
     542            0 :                 break;
     543              : 
     544              :         case PIO_UNIMAP:
     545              :         case GIO_UNIMAP:
     546            0 :                 return do_unimap_ioctl(cmd, up, perm, vc);
     547              : 
     548              :         default:
     549            0 :                 return -ENOIOCTLCMD;
     550              :         }
     551              : 
     552            0 :         return 0;
     553            0 : }
     554              : 
     555            0 : static int vt_reldisp(struct vc_data *vc, unsigned int swtch)
     556              : {
     557            0 :         int newvt, ret;
     558              : 
     559            0 :         if (vc->vt_mode.mode != VT_PROCESS)
     560            0 :                 return -EINVAL;
     561              : 
     562              :         /* Switched-to response */
     563            0 :         if (vc->vt_newvt < 0) {
     564              :                  /* If it's just an ACK, ignore it */
     565            0 :                 return swtch == VT_ACKACQ ? 0 : -EINVAL;
     566              :         }
     567              : 
     568              :         /* Switching-from response */
     569            0 :         if (swtch == 0) {
     570              :                 /* Switch disallowed, so forget we were trying to do it. */
     571            0 :                 vc->vt_newvt = -1;
     572            0 :                 return 0;
     573              :         }
     574              : 
     575              :         /* The current vt has been released, so complete the switch. */
     576            0 :         newvt = vc->vt_newvt;
     577            0 :         vc->vt_newvt = -1;
     578            0 :         ret = vc_allocate(newvt);
     579            0 :         if (ret)
     580            0 :                 return ret;
     581              : 
     582              :         /*
     583              :          * When we actually do the console switch, make sure we are atomic with
     584              :          * respect to other console switches..
     585              :          */
     586            0 :         complete_change_console(vc_cons[newvt].d);
     587              : 
     588            0 :         return 0;
     589            0 : }
     590              : 
     591            0 : static int vt_setactivate(struct vt_setactivate __user *sa)
     592              : {
     593            0 :         struct vt_setactivate vsa;
     594            0 :         struct vc_data *nvc;
     595            0 :         int ret;
     596              : 
     597            0 :         if (copy_from_user(&vsa, sa, sizeof(vsa)))
     598            0 :                 return -EFAULT;
     599            0 :         if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
     600            0 :                 return -ENXIO;
     601              : 
     602            0 :         vsa.console--;
     603            0 :         vsa.console = array_index_nospec(vsa.console, MAX_NR_CONSOLES);
     604            0 :         console_lock();
     605            0 :         ret = vc_allocate(vsa.console);
     606            0 :         if (ret) {
     607            0 :                 console_unlock();
     608            0 :                 return ret;
     609              :         }
     610              : 
     611              :         /*
     612              :          * This is safe providing we don't drop the console sem between
     613              :          * vc_allocate and finishing referencing nvc.
     614              :          */
     615            0 :         nvc = vc_cons[vsa.console].d;
     616            0 :         nvc->vt_mode = vsa.mode;
     617            0 :         nvc->vt_mode.frsig = 0;
     618            0 :         put_pid(nvc->vt_pid);
     619            0 :         nvc->vt_pid = get_pid(task_pid(current));
     620            0 :         console_unlock();
     621              : 
     622              :         /* Commence switch and lock */
     623              :         /* Review set_console locks */
     624            0 :         set_console(vsa.console);
     625              : 
     626            0 :         return 0;
     627            0 : }
     628              : 
     629              : /* deallocate a single console, if possible (leave 0) */
     630            0 : static int vt_disallocate(unsigned int vc_num)
     631              : {
     632            0 :         struct vc_data *vc = NULL;
     633            0 :         int ret = 0;
     634              : 
     635            0 :         console_lock();
     636            0 :         if (vt_busy(vc_num))
     637            0 :                 ret = -EBUSY;
     638            0 :         else if (vc_num)
     639            0 :                 vc = vc_deallocate(vc_num);
     640            0 :         console_unlock();
     641              : 
     642            0 :         if (vc && vc_num >= MIN_NR_CONSOLES)
     643            0 :                 tty_port_put(&vc->port);
     644              : 
     645            0 :         return ret;
     646            0 : }
     647              : 
     648              : /* deallocate all unused consoles, but leave 0 */
     649            0 : static void vt_disallocate_all(void)
     650              : {
     651            0 :         struct vc_data *vc[MAX_NR_CONSOLES];
     652            0 :         int i;
     653              : 
     654            0 :         console_lock();
     655            0 :         for (i = 1; i < MAX_NR_CONSOLES; i++)
     656            0 :                 if (!vt_busy(i))
     657            0 :                         vc[i] = vc_deallocate(i);
     658              :                 else
     659            0 :                         vc[i] = NULL;
     660            0 :         console_unlock();
     661              : 
     662            0 :         for (i = 1; i < MAX_NR_CONSOLES; i++) {
     663            0 :                 if (vc[i] && i >= MIN_NR_CONSOLES)
     664            0 :                         tty_port_put(&vc[i]->port);
     665            0 :         }
     666            0 : }
     667              : 
     668            0 : static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)
     669              : {
     670            0 :         struct vt_consize v;
     671            0 :         int i;
     672              : 
     673            0 :         if (copy_from_user(&v, cs, sizeof(struct vt_consize)))
     674            0 :                 return -EFAULT;
     675              : 
     676              :         /* FIXME: Should check the copies properly */
     677            0 :         if (!v.v_vlin)
     678            0 :                 v.v_vlin = vc->vc_scan_lines;
     679              : 
     680            0 :         if (v.v_clin) {
     681            0 :                 int rows = v.v_vlin / v.v_clin;
     682            0 :                 if (v.v_rows != rows) {
     683            0 :                         if (v.v_rows) /* Parameters don't add up */
     684            0 :                                 return -EINVAL;
     685            0 :                         v.v_rows = rows;
     686            0 :                 }
     687            0 :         }
     688              : 
     689            0 :         if (v.v_vcol && v.v_ccol) {
     690            0 :                 int cols = v.v_vcol / v.v_ccol;
     691            0 :                 if (v.v_cols != cols) {
     692            0 :                         if (v.v_cols)
     693            0 :                                 return -EINVAL;
     694            0 :                         v.v_cols = cols;
     695            0 :                 }
     696            0 :         }
     697              : 
     698            0 :         if (v.v_clin > 32)
     699            0 :                 return -EINVAL;
     700              : 
     701            0 :         for (i = 0; i < MAX_NR_CONSOLES; i++) {
     702            0 :                 struct vc_data *vcp;
     703              : 
     704            0 :                 if (!vc_cons[i].d)
     705            0 :                         continue;
     706            0 :                 console_lock();
     707            0 :                 vcp = vc_cons[i].d;
     708            0 :                 if (vcp) {
     709            0 :                         int ret;
     710            0 :                         int save_scan_lines = vcp->vc_scan_lines;
     711            0 :                         int save_cell_height = vcp->vc_cell_height;
     712              : 
     713            0 :                         if (v.v_vlin)
     714            0 :                                 vcp->vc_scan_lines = v.v_vlin;
     715            0 :                         if (v.v_clin)
     716            0 :                                 vcp->vc_cell_height = v.v_clin;
     717            0 :                         ret = __vc_resize(vcp, v.v_cols, v.v_rows, true);
     718            0 :                         if (ret) {
     719            0 :                                 vcp->vc_scan_lines = save_scan_lines;
     720            0 :                                 vcp->vc_cell_height = save_cell_height;
     721            0 :                                 console_unlock();
     722            0 :                                 return ret;
     723              :                         }
     724            0 :                 }
     725            0 :                 console_unlock();
     726            0 :         }
     727              : 
     728            0 :         return 0;
     729            0 : }
     730              : 
     731              : /*
     732              :  * We handle the console-specific ioctl's here.  We allow the
     733              :  * capability to modify any console, not just the fg_console.
     734              :  */
     735            0 : int vt_ioctl(struct tty_struct *tty,
     736              :              unsigned int cmd, unsigned long arg)
     737              : {
     738            0 :         struct vc_data *vc = tty->driver_data;
     739            0 :         void __user *up = (void __user *)arg;
     740            0 :         int i, perm;
     741            0 :         int ret;
     742              : 
     743              :         /*
     744              :          * To have permissions to do most of the vt ioctls, we either have
     745              :          * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
     746              :          */
     747            0 :         perm = 0;
     748            0 :         if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
     749            0 :                 perm = 1;
     750              : 
     751            0 :         ret = vt_k_ioctl(tty, cmd, arg, perm);
     752            0 :         if (ret != -ENOIOCTLCMD)
     753            0 :                 return ret;
     754              : 
     755            0 :         ret = vt_io_ioctl(vc, cmd, up, perm);
     756            0 :         if (ret != -ENOIOCTLCMD)
     757            0 :                 return ret;
     758              : 
     759            0 :         switch (cmd) {
     760              :         case TIOCLINUX:
     761            0 :                 return tioclinux(tty, arg);
     762              :         case VT_SETMODE:
     763              :         {
     764            0 :                 struct vt_mode tmp;
     765              : 
     766            0 :                 if (!perm)
     767            0 :                         return -EPERM;
     768            0 :                 if (copy_from_user(&tmp, up, sizeof(struct vt_mode)))
     769            0 :                         return -EFAULT;
     770            0 :                 if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
     771            0 :                         return -EINVAL;
     772              : 
     773            0 :                 console_lock();
     774            0 :                 vc->vt_mode = tmp;
     775              :                 /* the frsig is ignored, so we set it to 0 */
     776            0 :                 vc->vt_mode.frsig = 0;
     777            0 :                 put_pid(vc->vt_pid);
     778            0 :                 vc->vt_pid = get_pid(task_pid(current));
     779              :                 /* no switch is required -- [email protected] */
     780            0 :                 vc->vt_newvt = -1;
     781            0 :                 console_unlock();
     782            0 :                 break;
     783            0 :         }
     784              : 
     785              :         case VT_GETMODE:
     786              :         {
     787            0 :                 struct vt_mode tmp;
     788            0 :                 int rc;
     789              : 
     790            0 :                 console_lock();
     791            0 :                 memcpy(&tmp, &vc->vt_mode, sizeof(struct vt_mode));
     792            0 :                 console_unlock();
     793              : 
     794            0 :                 rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
     795            0 :                 if (rc)
     796            0 :                         return -EFAULT;
     797            0 :                 break;
     798            0 :         }
     799              : 
     800              :         /*
     801              :          * Returns global vt state. Note that VT 0 is always open, since
     802              :          * it's an alias for the current VT, and people can't use it here.
     803              :          * We cannot return state for more than 16 VTs, since v_state is short.
     804              :          */
     805              :         case VT_GETSTATE:
     806              :         {
     807            0 :                 struct vt_stat __user *vtstat = up;
     808            0 :                 unsigned short state, mask;
     809              : 
     810            0 :                 if (put_user(fg_console + 1, &vtstat->v_active))
     811            0 :                         return -EFAULT;
     812              : 
     813            0 :                 state = 1;      /* /dev/tty0 is always open */
     814            0 :                 console_lock(); /* required by vt_in_use() */
     815            0 :                 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
     816            0 :                                 ++i, mask <<= 1)
     817            0 :                         if (vt_in_use(i))
     818            0 :                                 state |= mask;
     819            0 :                 console_unlock();
     820            0 :                 return put_user(state, &vtstat->v_state);
     821            0 :         }
     822              : 
     823              :         /*
     824              :          * Returns the first available (non-opened) console.
     825              :          */
     826              :         case VT_OPENQRY:
     827            0 :                 console_lock(); /* required by vt_in_use() */
     828            0 :                 for (i = 0; i < MAX_NR_CONSOLES; ++i)
     829            0 :                         if (!vt_in_use(i))
     830            0 :                                 break;
     831            0 :                 console_unlock();
     832            0 :                 i = i < MAX_NR_CONSOLES ? (i+1) : -1;
     833            0 :                 return put_user(i, (int __user *)arg);
     834              : 
     835              :         /*
     836              :          * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
     837              :          * with num >= 1 (switches to vt 0, our console, are not allowed, just
     838              :          * to preserve sanity).
     839              :          */
     840              :         case VT_ACTIVATE:
     841            0 :                 if (!perm)
     842            0 :                         return -EPERM;
     843            0 :                 if (arg == 0 || arg > MAX_NR_CONSOLES)
     844            0 :                         return -ENXIO;
     845              : 
     846            0 :                 arg--;
     847            0 :                 arg = array_index_nospec(arg, MAX_NR_CONSOLES);
     848            0 :                 console_lock();
     849            0 :                 ret = vc_allocate(arg);
     850            0 :                 console_unlock();
     851            0 :                 if (ret)
     852            0 :                         return ret;
     853            0 :                 set_console(arg);
     854            0 :                 break;
     855              : 
     856              :         case VT_SETACTIVATE:
     857            0 :                 if (!perm)
     858            0 :                         return -EPERM;
     859              : 
     860            0 :                 return vt_setactivate(up);
     861              : 
     862              :         /*
     863              :          * wait until the specified VT has been activated
     864              :          */
     865              :         case VT_WAITACTIVE:
     866            0 :                 if (!perm)
     867            0 :                         return -EPERM;
     868            0 :                 if (arg == 0 || arg > MAX_NR_CONSOLES)
     869            0 :                         return -ENXIO;
     870            0 :                 return vt_waitactive(arg);
     871              : 
     872              :         /*
     873              :          * If a vt is under process control, the kernel will not switch to it
     874              :          * immediately, but postpone the operation until the process calls this
     875              :          * ioctl, allowing the switch to complete.
     876              :          *
     877              :          * According to the X sources this is the behavior:
     878              :          *      0:      pending switch-from not OK
     879              :          *      1:      pending switch-from OK
     880              :          *      2:      completed switch-to OK
     881              :          */
     882              :         case VT_RELDISP:
     883            0 :                 if (!perm)
     884            0 :                         return -EPERM;
     885              : 
     886            0 :                 console_lock();
     887            0 :                 ret = vt_reldisp(vc, arg);
     888            0 :                 console_unlock();
     889              : 
     890            0 :                 return ret;
     891              : 
     892              : 
     893              :          /*
     894              :           * Disallocate memory associated to VT (but leave VT1)
     895              :           */
     896              :          case VT_DISALLOCATE:
     897            0 :                 if (arg > MAX_NR_CONSOLES)
     898            0 :                         return -ENXIO;
     899              : 
     900            0 :                 if (arg == 0) {
     901            0 :                         vt_disallocate_all();
     902            0 :                         break;
     903              :                 }
     904              : 
     905            0 :                 arg = array_index_nospec(arg - 1, MAX_NR_CONSOLES);
     906            0 :                 return vt_disallocate(arg);
     907              : 
     908              :         case VT_RESIZE:
     909              :         {
     910            0 :                 struct vt_sizes __user *vtsizes = up;
     911            0 :                 struct vc_data *vc;
     912            0 :                 ushort ll,cc;
     913              : 
     914            0 :                 if (!perm)
     915            0 :                         return -EPERM;
     916            0 :                 if (get_user(ll, &vtsizes->v_rows) ||
     917            0 :                     get_user(cc, &vtsizes->v_cols))
     918            0 :                         return -EFAULT;
     919              : 
     920            0 :                 console_lock();
     921            0 :                 for (i = 0; i < MAX_NR_CONSOLES; i++) {
     922            0 :                         vc = vc_cons[i].d;
     923              : 
     924            0 :                         if (vc) {
     925              :                                 /* FIXME: review v tty lock */
     926            0 :                                 __vc_resize(vc_cons[i].d, cc, ll, true);
     927            0 :                         }
     928            0 :                 }
     929            0 :                 console_unlock();
     930            0 :                 break;
     931            0 :         }
     932              : 
     933              :         case VT_RESIZEX:
     934            0 :                 if (!perm)
     935            0 :                         return -EPERM;
     936              : 
     937            0 :                 return vt_resizex(vc, up);
     938              : 
     939              :         case VT_LOCKSWITCH:
     940            0 :                 if (!capable(CAP_SYS_TTY_CONFIG))
     941            0 :                         return -EPERM;
     942            0 :                 vt_dont_switch = true;
     943            0 :                 break;
     944              :         case VT_UNLOCKSWITCH:
     945            0 :                 if (!capable(CAP_SYS_TTY_CONFIG))
     946            0 :                         return -EPERM;
     947            0 :                 vt_dont_switch = false;
     948            0 :                 break;
     949              :         case VT_GETHIFONTMASK:
     950            0 :                 return put_user(vc->vc_hi_font_mask,
     951              :                                         (unsigned short __user *)arg);
     952              :         case VT_WAITEVENT:
     953            0 :                 return vt_event_wait_ioctl((struct vt_event __user *)arg);
     954              : 
     955              :         case VT_GETCONSIZECSRPOS:
     956              :         {
     957            0 :                 struct vt_consizecsrpos concsr;
     958              : 
     959            0 :                 console_lock();
     960            0 :                 concsr.con_cols = vc->vc_cols;
     961            0 :                 concsr.con_rows = vc->vc_rows;
     962            0 :                 concsr.csr_col = vc->state.x;
     963            0 :                 concsr.csr_row = vc->state.y;
     964            0 :                 console_unlock();
     965            0 :                 if (copy_to_user(up, &concsr, sizeof(concsr)))
     966            0 :                         return -EFAULT;
     967            0 :                 return 0;
     968            0 :         }
     969              : 
     970              :         default:
     971            0 :                 return -ENOIOCTLCMD;
     972              :         }
     973              : 
     974            0 :         return 0;
     975            0 : }
     976              : 
     977            0 : void reset_vc(struct vc_data *vc)
     978              : {
     979            0 :         vc->vc_mode = KD_TEXT;
     980            0 :         vt_reset_unicode(vc->vc_num);
     981            0 :         vc->vt_mode.mode = VT_AUTO;
     982            0 :         vc->vt_mode.waitv = 0;
     983            0 :         vc->vt_mode.relsig = 0;
     984            0 :         vc->vt_mode.acqsig = 0;
     985            0 :         vc->vt_mode.frsig = 0;
     986            0 :         put_pid(vc->vt_pid);
     987            0 :         vc->vt_pid = NULL;
     988            0 :         vc->vt_newvt = -1;
     989            0 :         reset_palette(vc);
     990            0 : }
     991              : 
     992            0 : void vc_SAK(struct work_struct *work)
     993              : {
     994            0 :         struct vc *vc_con =
     995            0 :                 container_of(work, struct vc, SAK_work);
     996            0 :         struct vc_data *vc;
     997            0 :         struct tty_struct *tty;
     998              : 
     999            0 :         console_lock();
    1000            0 :         vc = vc_con->d;
    1001            0 :         if (vc) {
    1002              :                 /* FIXME: review tty ref counting */
    1003            0 :                 tty = vc->port.tty;
    1004              :                 /*
    1005              :                  * SAK should also work in all raw modes and reset
    1006              :                  * them properly.
    1007              :                  */
    1008            0 :                 if (tty)
    1009            0 :                         __do_SAK(tty);
    1010            0 :                 reset_vc(vc);
    1011            0 :         }
    1012            0 :         console_unlock();
    1013            0 : }
    1014              : 
    1015              : #ifdef CONFIG_COMPAT
    1016              : 
    1017              : struct compat_console_font_op {
    1018              :         compat_uint_t op;        /* operation code KD_FONT_OP_* */
    1019              :         compat_uint_t flags;     /* KD_FONT_FLAG_* */
    1020              :         compat_uint_t width, height;     /* font size */
    1021              :         compat_uint_t charcount;
    1022              :         compat_caddr_t data;    /* font data with height fixed to 32 */
    1023              : };
    1024              : 
    1025              : static inline int
    1026            0 : compat_kdfontop_ioctl(struct compat_console_font_op __user *fontop,
    1027              :                          int perm, struct console_font_op *op, struct vc_data *vc)
    1028              : {
    1029            0 :         int i;
    1030              : 
    1031            0 :         if (copy_from_user(op, fontop, sizeof(struct compat_console_font_op)))
    1032            0 :                 return -EFAULT;
    1033            0 :         if (!perm && op->op != KD_FONT_OP_GET)
    1034            0 :                 return -EPERM;
    1035            0 :         op->data = compat_ptr(((struct compat_console_font_op *)op)->data);
    1036            0 :         i = con_font_op(vc, op);
    1037            0 :         if (i)
    1038            0 :                 return i;
    1039            0 :         ((struct compat_console_font_op *)op)->data = (unsigned long)op->data;
    1040            0 :         if (copy_to_user(fontop, op, sizeof(struct compat_console_font_op)))
    1041            0 :                 return -EFAULT;
    1042            0 :         return 0;
    1043            0 : }
    1044              : 
    1045              : struct compat_unimapdesc {
    1046              :         unsigned short entry_ct;
    1047              :         compat_caddr_t entries;
    1048              : };
    1049              : 
    1050              : static inline int
    1051            0 : compat_unimap_ioctl(unsigned int cmd, struct compat_unimapdesc __user *user_ud,
    1052              :                          int perm, struct vc_data *vc)
    1053              : {
    1054            0 :         struct compat_unimapdesc tmp;
    1055            0 :         struct unipair __user *tmp_entries;
    1056              : 
    1057            0 :         if (copy_from_user(&tmp, user_ud, sizeof tmp))
    1058            0 :                 return -EFAULT;
    1059            0 :         tmp_entries = compat_ptr(tmp.entries);
    1060            0 :         switch (cmd) {
    1061              :         case PIO_UNIMAP:
    1062            0 :                 if (!perm)
    1063            0 :                         return -EPERM;
    1064            0 :                 return con_set_unimap(vc, tmp.entry_ct, tmp_entries);
    1065              :         case GIO_UNIMAP:
    1066            0 :                 if (!perm && fg_console != vc->vc_num)
    1067            0 :                         return -EPERM;
    1068            0 :                 return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp_entries);
    1069              :         }
    1070            0 :         return 0;
    1071            0 : }
    1072              : 
    1073            0 : long vt_compat_ioctl(struct tty_struct *tty,
    1074              :              unsigned int cmd, unsigned long arg)
    1075              : {
    1076            0 :         struct vc_data *vc = tty->driver_data;
    1077            0 :         struct console_font_op op;      /* used in multiple places here */
    1078            0 :         void __user *up = compat_ptr(arg);
    1079            0 :         int perm;
    1080              : 
    1081              :         /*
    1082              :          * To have permissions to do most of the vt ioctls, we either have
    1083              :          * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG.
    1084              :          */
    1085            0 :         perm = 0;
    1086            0 :         if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
    1087            0 :                 perm = 1;
    1088              : 
    1089            0 :         switch (cmd) {
    1090              :         /*
    1091              :          * these need special handlers for incompatible data structures
    1092              :          */
    1093              : 
    1094              :         case KDFONTOP:
    1095            0 :                 return compat_kdfontop_ioctl(up, perm, &op, vc);
    1096              : 
    1097              :         case PIO_UNIMAP:
    1098              :         case GIO_UNIMAP:
    1099            0 :                 return compat_unimap_ioctl(cmd, up, perm, vc);
    1100              : 
    1101              :         /*
    1102              :          * all these treat 'arg' as an integer
    1103              :          */
    1104              :         case KIOCSOUND:
    1105              :         case KDMKTONE:
    1106              : #ifdef CONFIG_X86
    1107              :         case KDADDIO:
    1108              :         case KDDELIO:
    1109              : #endif
    1110              :         case KDSETMODE:
    1111              :         case KDMAPDISP:
    1112              :         case KDUNMAPDISP:
    1113              :         case KDSKBMODE:
    1114              :         case KDSKBMETA:
    1115              :         case KDSKBLED:
    1116              :         case KDSETLED:
    1117              :         case KDSIGACCEPT:
    1118              :         case VT_ACTIVATE:
    1119              :         case VT_WAITACTIVE:
    1120              :         case VT_RELDISP:
    1121              :         case VT_DISALLOCATE:
    1122            0 :                 return vt_ioctl(tty, cmd, arg);
    1123              : 
    1124              :         /*
    1125              :          * the rest has a compatible data structure behind arg,
    1126              :          * but we have to convert it to a proper 64 bit pointer.
    1127              :          */
    1128              :         default:
    1129            0 :                 return vt_ioctl(tty, cmd, (unsigned long)up);
    1130              :         }
    1131            0 : }
    1132              : 
    1133              : 
    1134              : #endif /* CONFIG_COMPAT */
    1135              : 
    1136              : 
    1137              : /*
    1138              :  * Performs the back end of a vt switch. Called under the console
    1139              :  * semaphore.
    1140              :  */
    1141            0 : static void complete_change_console(struct vc_data *vc)
    1142              : {
    1143            0 :         unsigned char old_vc_mode;
    1144            0 :         int old = fg_console;
    1145              : 
    1146            0 :         last_console = fg_console;
    1147              : 
    1148              :         /*
    1149              :          * If we're switching, we could be going from KD_GRAPHICS to
    1150              :          * KD_TEXT mode or vice versa, which means we need to blank or
    1151              :          * unblank the screen later.
    1152              :          */
    1153            0 :         old_vc_mode = vc_cons[fg_console].d->vc_mode;
    1154            0 :         switch_screen(vc);
    1155              : 
    1156              :         /*
    1157              :          * This can't appear below a successful kill_pid().  If it did,
    1158              :          * then the *blank_screen operation could occur while X, having
    1159              :          * received acqsig, is waking up on another processor.  This
    1160              :          * condition can lead to overlapping accesses to the VGA range
    1161              :          * and the framebuffer (causing system lockups).
    1162              :          *
    1163              :          * To account for this we duplicate this code below only if the
    1164              :          * controlling process is gone and we've called reset_vc.
    1165              :          */
    1166            0 :         if (old_vc_mode != vc->vc_mode) {
    1167            0 :                 if (vc->vc_mode == KD_TEXT)
    1168            0 :                         do_unblank_screen(1);
    1169              :                 else
    1170            0 :                         do_blank_screen(1);
    1171            0 :         }
    1172              : 
    1173              :         /*
    1174              :          * If this new console is under process control, send it a signal
    1175              :          * telling it that it has acquired. Also check if it has died and
    1176              :          * clean up (similar to logic employed in change_console())
    1177              :          */
    1178            0 :         if (vc->vt_mode.mode == VT_PROCESS) {
    1179              :                 /*
    1180              :                  * Send the signal as privileged - kill_pid() will
    1181              :                  * tell us if the process has gone or something else
    1182              :                  * is awry
    1183              :                  */
    1184            0 :                 if (kill_pid(vc->vt_pid, vc->vt_mode.acqsig, 1) != 0) {
    1185              :                 /*
    1186              :                  * The controlling process has died, so we revert back to
    1187              :                  * normal operation. In this case, we'll also change back
    1188              :                  * to KD_TEXT mode. I'm not sure if this is strictly correct
    1189              :                  * but it saves the agony when the X server dies and the screen
    1190              :                  * remains blanked due to KD_GRAPHICS! It would be nice to do
    1191              :                  * this outside of VT_PROCESS but there is no single process
    1192              :                  * to account for and tracking tty count may be undesirable.
    1193              :                  */
    1194            0 :                         reset_vc(vc);
    1195              : 
    1196            0 :                         if (old_vc_mode != vc->vc_mode) {
    1197            0 :                                 if (vc->vc_mode == KD_TEXT)
    1198            0 :                                         do_unblank_screen(1);
    1199              :                                 else
    1200            0 :                                         do_blank_screen(1);
    1201            0 :                         }
    1202            0 :                 }
    1203            0 :         }
    1204              : 
    1205              :         /*
    1206              :          * Wake anyone waiting for their VT to activate
    1207              :          */
    1208            0 :         vt_event_post(VT_EVENT_SWITCH, old, vc->vc_num);
    1209              :         return;
    1210            0 : }
    1211              : 
    1212              : /*
    1213              :  * Performs the front-end of a vt switch
    1214              :  */
    1215            0 : void change_console(struct vc_data *new_vc)
    1216              : {
    1217            0 :         struct vc_data *vc;
    1218              : 
    1219            0 :         if (!new_vc || new_vc->vc_num == fg_console || vt_dont_switch)
    1220            0 :                 return;
    1221              : 
    1222              :         /*
    1223              :          * If this vt is in process mode, then we need to handshake with
    1224              :          * that process before switching. Essentially, we store where that
    1225              :          * vt wants to switch to and wait for it to tell us when it's done
    1226              :          * (via VT_RELDISP ioctl).
    1227              :          *
    1228              :          * We also check to see if the controlling process still exists.
    1229              :          * If it doesn't, we reset this vt to auto mode and continue.
    1230              :          * This is a cheap way to track process control. The worst thing
    1231              :          * that can happen is: we send a signal to a process, it dies, and
    1232              :          * the switch gets "lost" waiting for a response; hopefully, the
    1233              :          * user will try again, we'll detect the process is gone (unless
    1234              :          * the user waits just the right amount of time :-) and revert the
    1235              :          * vt to auto control.
    1236              :          */
    1237            0 :         vc = vc_cons[fg_console].d;
    1238            0 :         if (vc->vt_mode.mode == VT_PROCESS) {
    1239              :                 /*
    1240              :                  * Send the signal as privileged - kill_pid() will
    1241              :                  * tell us if the process has gone or something else
    1242              :                  * is awry.
    1243              :                  *
    1244              :                  * We need to set vt_newvt *before* sending the signal or we
    1245              :                  * have a race.
    1246              :                  */
    1247            0 :                 vc->vt_newvt = new_vc->vc_num;
    1248            0 :                 if (kill_pid(vc->vt_pid, vc->vt_mode.relsig, 1) == 0) {
    1249              :                         /*
    1250              :                          * It worked. Mark the vt to switch to and
    1251              :                          * return. The process needs to send us a
    1252              :                          * VT_RELDISP ioctl to complete the switch.
    1253              :                          */
    1254            0 :                         return;
    1255              :                 }
    1256              : 
    1257              :                 /*
    1258              :                  * The controlling process has died, so we revert back to
    1259              :                  * normal operation. In this case, we'll also change back
    1260              :                  * to KD_TEXT mode. I'm not sure if this is strictly correct
    1261              :                  * but it saves the agony when the X server dies and the screen
    1262              :                  * remains blanked due to KD_GRAPHICS! It would be nice to do
    1263              :                  * this outside of VT_PROCESS but there is no single process
    1264              :                  * to account for and tracking tty count may be undesirable.
    1265              :                  */
    1266            0 :                 reset_vc(vc);
    1267              : 
    1268              :                 /*
    1269              :                  * Fall through to normal (VT_AUTO) handling of the switch...
    1270              :                  */
    1271            0 :         }
    1272              : 
    1273              :         /*
    1274              :          * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
    1275              :          */
    1276            0 :         if (vc->vc_mode == KD_GRAPHICS)
    1277            0 :                 return;
    1278              : 
    1279            0 :         complete_change_console(new_vc);
    1280            0 : }
    1281              : 
    1282              : /* Perform a kernel triggered VT switch for suspend/resume */
    1283              : 
    1284              : static int disable_vt_switch;
    1285              : 
    1286            0 : int vt_move_to_console(unsigned int vt, int alloc)
    1287              : {
    1288            0 :         int prev;
    1289              : 
    1290            0 :         console_lock();
    1291              :         /* Graphics mode - up to X */
    1292            0 :         if (disable_vt_switch) {
    1293            0 :                 console_unlock();
    1294            0 :                 return 0;
    1295              :         }
    1296            0 :         prev = fg_console;
    1297              : 
    1298            0 :         if (alloc && vc_allocate(vt)) {
    1299              :                 /* we can't have a free VC for now. Too bad,
    1300              :                  * we don't want to mess the screen for now. */
    1301            0 :                 console_unlock();
    1302            0 :                 return -ENOSPC;
    1303              :         }
    1304              : 
    1305            0 :         if (set_console(vt)) {
    1306              :                 /*
    1307              :                  * We're unable to switch to the SUSPEND_CONSOLE.
    1308              :                  * Let the calling function know so it can decide
    1309              :                  * what to do.
    1310              :                  */
    1311            0 :                 console_unlock();
    1312            0 :                 return -EIO;
    1313              :         }
    1314            0 :         console_unlock();
    1315            0 :         if (vt_waitactive(vt + 1)) {
    1316            0 :                 pr_debug("Suspend: Can't switch VCs.");
    1317            0 :                 return -EINTR;
    1318              :         }
    1319            0 :         return prev;
    1320            0 : }
    1321              : 
    1322              : /*
    1323              :  * Normally during a suspend, we allocate a new console and switch to it.
    1324              :  * When we resume, we switch back to the original console.  This switch
    1325              :  * can be slow, so on systems where the framebuffer can handle restoration
    1326              :  * of video registers anyways, there's little point in doing the console
    1327              :  * switch.  This function allows you to disable it by passing it '0'.
    1328              :  */
    1329            0 : void pm_set_vt_switch(int do_switch)
    1330              : {
    1331            0 :         console_lock();
    1332            0 :         disable_vt_switch = !do_switch;
    1333            0 :         console_unlock();
    1334            0 : }
    1335              : EXPORT_SYMBOL(pm_set_vt_switch);
        

Generated by: LCOV version 2.0-1