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