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