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