forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-11 072de836f53be56a70cecf70b43ae43b7ce17376
kernel/drivers/tty/vt/vt_ioctl.c
....@@ -181,7 +181,7 @@
181181
182182 /**
183183 * vt_event_wait_ioctl - event ioctl handler
184
- * @arg: argument to ioctl
184
+ * @event: argument to ioctl (the event)
185185 *
186186 * Implement the VT_WAITEVENT ioctl using the VT event interface
187187 */
....@@ -208,7 +208,6 @@
208208
209209 /**
210210 * vt_waitactive - active console wait
211
- * @event: event code
212211 * @n: new console
213212 *
214213 * Helper for event waits. Used to implement the legacy
....@@ -241,50 +240,254 @@
241240 #define GPLAST 0x3df
242241 #define GPNUM (GPLAST - GPFIRST + 1)
243242
244
-
245
-
246
-static inline int
247
-do_fontx_ioctl(struct vc_data *vc, int cmd, struct consolefontdesc __user *user_cfd, int perm, struct console_font_op *op)
243
+/*
244
+ * currently, setting the mode from KD_TEXT to KD_GRAPHICS doesn't do a whole
245
+ * lot. i'm not sure if it should do any restoration of modes or what...
246
+ *
247
+ * XXX It should at least call into the driver, fbdev's definitely need to
248
+ * restore their engine state. --BenH
249
+ *
250
+ * Called with the console lock held.
251
+ */
252
+static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
248253 {
249
- struct consolefontdesc cfdarg;
250
- int i;
251
-
252
- if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
253
- return -EFAULT;
254
-
255
- switch (cmd) {
256
- case PIO_FONTX:
257
- if (!perm)
258
- return -EPERM;
259
- op->op = KD_FONT_OP_SET;
260
- op->flags = KD_FONT_FLAG_OLD;
261
- op->width = 8;
262
- op->height = cfdarg.charheight;
263
- op->charcount = cfdarg.charcount;
264
- op->data = cfdarg.chardata;
265
- return con_font_op(vc, op);
266
-
267
- case GIO_FONTX:
268
- op->op = KD_FONT_OP_GET;
269
- op->flags = KD_FONT_FLAG_OLD;
270
- op->width = 8;
271
- op->height = cfdarg.charheight;
272
- op->charcount = cfdarg.charcount;
273
- op->data = cfdarg.chardata;
274
- i = con_font_op(vc, op);
275
- if (i)
276
- return i;
277
- cfdarg.charheight = op->height;
278
- cfdarg.charcount = op->charcount;
279
- if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
280
- return -EFAULT;
281
- return 0;
254
+ switch (mode) {
255
+ case KD_GRAPHICS:
256
+ break;
257
+ case KD_TEXT0:
258
+ case KD_TEXT1:
259
+ mode = KD_TEXT;
260
+ fallthrough;
261
+ case KD_TEXT:
262
+ break;
263
+ default:
264
+ return -EINVAL;
282265 }
283
- return -EINVAL;
266
+
267
+ if (vc->vc_mode == mode)
268
+ return 0;
269
+
270
+ vc->vc_mode = mode;
271
+ if (vc->vc_num != fg_console)
272
+ return 0;
273
+
274
+ /* explicitly blank/unblank the screen if switching modes */
275
+ if (mode == KD_TEXT)
276
+ do_unblank_screen(1);
277
+ else
278
+ do_blank_screen(1);
279
+
280
+ return 0;
284281 }
285282
286
-static inline int
287
-do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud, int perm, struct vc_data *vc)
283
+static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd,
284
+ unsigned long arg, bool perm)
285
+{
286
+ struct vc_data *vc = tty->driver_data;
287
+ void __user *up = (void __user *)arg;
288
+ unsigned int console = vc->vc_num;
289
+ int ret;
290
+
291
+ switch (cmd) {
292
+ case KIOCSOUND:
293
+ if (!perm)
294
+ return -EPERM;
295
+ /*
296
+ * The use of PIT_TICK_RATE is historic, it used to be
297
+ * the platform-dependent CLOCK_TICK_RATE between 2.6.12
298
+ * and 2.6.36, which was a minor but unfortunate ABI
299
+ * change. kd_mksound is locked by the input layer.
300
+ */
301
+ if (arg)
302
+ arg = PIT_TICK_RATE / arg;
303
+ kd_mksound(arg, 0);
304
+ break;
305
+
306
+ case KDMKTONE:
307
+ if (!perm)
308
+ return -EPERM;
309
+ {
310
+ unsigned int ticks, count;
311
+
312
+ /*
313
+ * Generate the tone for the appropriate number of ticks.
314
+ * If the time is zero, turn off sound ourselves.
315
+ */
316
+ ticks = msecs_to_jiffies((arg >> 16) & 0xffff);
317
+ count = ticks ? (arg & 0xffff) : 0;
318
+ if (count)
319
+ count = PIT_TICK_RATE / count;
320
+ kd_mksound(count, ticks);
321
+ break;
322
+ }
323
+
324
+ case KDGKBTYPE:
325
+ /*
326
+ * this is naïve.
327
+ */
328
+ return put_user(KB_101, (char __user *)arg);
329
+
330
+ /*
331
+ * These cannot be implemented on any machine that implements
332
+ * ioperm() in user level (such as Alpha PCs) or not at all.
333
+ *
334
+ * XXX: you should never use these, just call ioperm directly..
335
+ */
336
+#ifdef CONFIG_X86
337
+ case KDADDIO:
338
+ case KDDELIO:
339
+ /*
340
+ * KDADDIO and KDDELIO may be able to add ports beyond what
341
+ * we reject here, but to be safe...
342
+ *
343
+ * These are locked internally via sys_ioperm
344
+ */
345
+ if (arg < GPFIRST || arg > GPLAST)
346
+ return -EINVAL;
347
+
348
+ return ksys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
349
+
350
+ case KDENABIO:
351
+ case KDDISABIO:
352
+ return ksys_ioperm(GPFIRST, GPNUM,
353
+ (cmd == KDENABIO)) ? -ENXIO : 0;
354
+#endif
355
+
356
+ /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
357
+
358
+ case KDKBDREP:
359
+ {
360
+ struct kbd_repeat kbrep;
361
+
362
+ if (!capable(CAP_SYS_TTY_CONFIG))
363
+ return -EPERM;
364
+
365
+ if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat)))
366
+ return -EFAULT;
367
+
368
+ ret = kbd_rate(&kbrep);
369
+ if (ret)
370
+ return ret;
371
+ if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
372
+ return -EFAULT;
373
+ break;
374
+ }
375
+
376
+ case KDSETMODE:
377
+ if (!perm)
378
+ return -EPERM;
379
+
380
+ console_lock();
381
+ ret = vt_kdsetmode(vc, arg);
382
+ console_unlock();
383
+ return ret;
384
+
385
+ case KDGETMODE:
386
+ return put_user(vc->vc_mode, (int __user *)arg);
387
+
388
+ case KDMAPDISP:
389
+ case KDUNMAPDISP:
390
+ /*
391
+ * these work like a combination of mmap and KDENABIO.
392
+ * this could be easily finished.
393
+ */
394
+ return -EINVAL;
395
+
396
+ case KDSKBMODE:
397
+ if (!perm)
398
+ return -EPERM;
399
+ ret = vt_do_kdskbmode(console, arg);
400
+ if (ret)
401
+ return ret;
402
+ tty_ldisc_flush(tty);
403
+ break;
404
+
405
+ case KDGKBMODE:
406
+ return put_user(vt_do_kdgkbmode(console), (int __user *)arg);
407
+
408
+ /* this could be folded into KDSKBMODE, but for compatibility
409
+ reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
410
+ case KDSKBMETA:
411
+ return vt_do_kdskbmeta(console, arg);
412
+
413
+ case KDGKBMETA:
414
+ /* FIXME: should review whether this is worth locking */
415
+ return put_user(vt_do_kdgkbmeta(console), (int __user *)arg);
416
+
417
+ case KDGETKEYCODE:
418
+ case KDSETKEYCODE:
419
+ if(!capable(CAP_SYS_TTY_CONFIG))
420
+ perm = 0;
421
+ return vt_do_kbkeycode_ioctl(cmd, up, perm);
422
+
423
+ case KDGKBENT:
424
+ case KDSKBENT:
425
+ return vt_do_kdsk_ioctl(cmd, up, perm, console);
426
+
427
+ case KDGKBSENT:
428
+ case KDSKBSENT:
429
+ return vt_do_kdgkb_ioctl(cmd, up, perm);
430
+
431
+ /* Diacritical processing. Handled in keyboard.c as it has
432
+ to operate on the keyboard locks and structures */
433
+ case KDGKBDIACR:
434
+ case KDGKBDIACRUC:
435
+ case KDSKBDIACR:
436
+ case KDSKBDIACRUC:
437
+ return vt_do_diacrit(cmd, up, perm);
438
+
439
+ /* the ioctls below read/set the flags usually shown in the leds */
440
+ /* don't use them - they will go away without warning */
441
+ case KDGKBLED:
442
+ case KDSKBLED:
443
+ case KDGETLED:
444
+ case KDSETLED:
445
+ return vt_do_kdskled(console, cmd, arg, perm);
446
+
447
+ /*
448
+ * A process can indicate its willingness to accept signals
449
+ * generated by pressing an appropriate key combination.
450
+ * Thus, one can have a daemon that e.g. spawns a new console
451
+ * upon a keypress and then changes to it.
452
+ * See also the kbrequest field of inittab(5).
453
+ */
454
+ case KDSIGACCEPT:
455
+ if (!perm || !capable(CAP_KILL))
456
+ return -EPERM;
457
+ if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
458
+ return -EINVAL;
459
+
460
+ spin_lock_irq(&vt_spawn_con.lock);
461
+ put_pid(vt_spawn_con.pid);
462
+ vt_spawn_con.pid = get_pid(task_pid(current));
463
+ vt_spawn_con.sig = arg;
464
+ spin_unlock_irq(&vt_spawn_con.lock);
465
+ break;
466
+
467
+ case KDFONTOP: {
468
+ struct console_font_op op;
469
+
470
+ if (copy_from_user(&op, up, sizeof(op)))
471
+ return -EFAULT;
472
+ if (!perm && op.op != KD_FONT_OP_GET)
473
+ return -EPERM;
474
+ ret = con_font_op(vc, &op);
475
+ if (ret)
476
+ return ret;
477
+ if (copy_to_user(up, &op, sizeof(op)))
478
+ return -EFAULT;
479
+ break;
480
+ }
481
+
482
+ default:
483
+ return -ENOIOCTLCMD;
484
+ }
485
+
486
+ return 0;
487
+}
488
+
489
+static inline int do_unimap_ioctl(int cmd, struct unimapdesc __user *user_ud,
490
+ bool perm, struct vc_data *vc)
288491 {
289492 struct unimapdesc tmp;
290493
....@@ -298,8 +501,128 @@
298501 case GIO_UNIMAP:
299502 if (!perm && fg_console != vc->vc_num)
300503 return -EPERM;
301
- return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
504
+ return con_get_unimap(vc, tmp.entry_ct, &(user_ud->entry_ct),
505
+ tmp.entries);
302506 }
507
+ return 0;
508
+}
509
+
510
+static int vt_io_ioctl(struct vc_data *vc, unsigned int cmd, void __user *up,
511
+ bool perm)
512
+{
513
+ switch (cmd) {
514
+ case PIO_CMAP:
515
+ if (!perm)
516
+ return -EPERM;
517
+ return con_set_cmap(up);
518
+
519
+ case GIO_CMAP:
520
+ return con_get_cmap(up);
521
+
522
+ case PIO_SCRNMAP:
523
+ if (!perm)
524
+ return -EPERM;
525
+ return con_set_trans_old(up);
526
+
527
+ case GIO_SCRNMAP:
528
+ return con_get_trans_old(up);
529
+
530
+ case PIO_UNISCRNMAP:
531
+ if (!perm)
532
+ return -EPERM;
533
+ return con_set_trans_new(up);
534
+
535
+ case GIO_UNISCRNMAP:
536
+ return con_get_trans_new(up);
537
+
538
+ case PIO_UNIMAPCLR:
539
+ if (!perm)
540
+ return -EPERM;
541
+ con_clear_unimap(vc);
542
+ break;
543
+
544
+ case PIO_UNIMAP:
545
+ case GIO_UNIMAP:
546
+ return do_unimap_ioctl(cmd, up, perm, vc);
547
+
548
+ default:
549
+ return -ENOIOCTLCMD;
550
+ }
551
+
552
+ return 0;
553
+}
554
+
555
+static int vt_reldisp(struct vc_data *vc, unsigned int swtch)
556
+{
557
+ int newvt, ret;
558
+
559
+ if (vc->vt_mode.mode != VT_PROCESS)
560
+ return -EINVAL;
561
+
562
+ /* Switched-to response */
563
+ if (vc->vt_newvt < 0) {
564
+ /* If it's just an ACK, ignore it */
565
+ return swtch == VT_ACKACQ ? 0 : -EINVAL;
566
+ }
567
+
568
+ /* Switching-from response */
569
+ if (swtch == 0) {
570
+ /* Switch disallowed, so forget we were trying to do it. */
571
+ vc->vt_newvt = -1;
572
+ return 0;
573
+ }
574
+
575
+ /* The current vt has been released, so complete the switch. */
576
+ newvt = vc->vt_newvt;
577
+ vc->vt_newvt = -1;
578
+ ret = vc_allocate(newvt);
579
+ if (ret)
580
+ return ret;
581
+
582
+ /*
583
+ * When we actually do the console switch, make sure we are atomic with
584
+ * respect to other console switches..
585
+ */
586
+ complete_change_console(vc_cons[newvt].d);
587
+
588
+ return 0;
589
+}
590
+
591
+static int vt_setactivate(struct vt_setactivate __user *sa)
592
+{
593
+ struct vt_setactivate vsa;
594
+ struct vc_data *nvc;
595
+ int ret;
596
+
597
+ if (copy_from_user(&vsa, sa, sizeof(vsa)))
598
+ return -EFAULT;
599
+ if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
600
+ return -ENXIO;
601
+
602
+ vsa.console--;
603
+ vsa.console = array_index_nospec(vsa.console, MAX_NR_CONSOLES);
604
+ console_lock();
605
+ ret = vc_allocate(vsa.console);
606
+ if (ret) {
607
+ console_unlock();
608
+ return ret;
609
+ }
610
+
611
+ /*
612
+ * This is safe providing we don't drop the console sem between
613
+ * vc_allocate and finishing referencing nvc.
614
+ */
615
+ nvc = vc_cons[vsa.console].d;
616
+ nvc->vt_mode = vsa.mode;
617
+ nvc->vt_mode.frsig = 0;
618
+ put_pid(nvc->vt_pid);
619
+ nvc->vt_pid = get_pid(task_pid(current));
620
+ console_unlock();
621
+
622
+ /* Commence switch and lock */
623
+ /* Review set_console locks */
624
+ set_console(vsa.console);
625
+
303626 return 0;
304627 }
305628
....@@ -342,22 +665,81 @@
342665 }
343666 }
344667
668
+static int vt_resizex(struct vc_data *vc, struct vt_consize __user *cs)
669
+{
670
+ struct vt_consize v;
671
+ int i;
672
+
673
+ if (copy_from_user(&v, cs, sizeof(struct vt_consize)))
674
+ return -EFAULT;
675
+
676
+ /* FIXME: Should check the copies properly */
677
+ if (!v.v_vlin)
678
+ v.v_vlin = vc->vc_scan_lines;
679
+
680
+ if (v.v_clin) {
681
+ int rows = v.v_vlin / v.v_clin;
682
+ if (v.v_rows != rows) {
683
+ if (v.v_rows) /* Parameters don't add up */
684
+ return -EINVAL;
685
+ v.v_rows = rows;
686
+ }
687
+ }
688
+
689
+ if (v.v_vcol && v.v_ccol) {
690
+ int cols = v.v_vcol / v.v_ccol;
691
+ if (v.v_cols != cols) {
692
+ if (v.v_cols)
693
+ return -EINVAL;
694
+ v.v_cols = cols;
695
+ }
696
+ }
697
+
698
+ if (v.v_clin > 32)
699
+ return -EINVAL;
700
+
701
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
702
+ struct vc_data *vcp;
703
+
704
+ if (!vc_cons[i].d)
705
+ continue;
706
+ console_lock();
707
+ vcp = vc_cons[i].d;
708
+ if (vcp) {
709
+ int ret;
710
+ int save_scan_lines = vcp->vc_scan_lines;
711
+ int save_cell_height = vcp->vc_cell_height;
712
+
713
+ if (v.v_vlin)
714
+ vcp->vc_scan_lines = v.v_vlin;
715
+ if (v.v_clin)
716
+ vcp->vc_cell_height = v.v_clin;
717
+ vcp->vc_resize_user = 1;
718
+ ret = vc_resize(vcp, v.v_cols, v.v_rows);
719
+ if (ret) {
720
+ vcp->vc_scan_lines = save_scan_lines;
721
+ vcp->vc_cell_height = save_cell_height;
722
+ console_unlock();
723
+ return ret;
724
+ }
725
+ }
726
+ console_unlock();
727
+ }
728
+
729
+ return 0;
730
+}
345731
346732 /*
347733 * We handle the console-specific ioctl's here. We allow the
348
- * capability to modify any console, not just the fg_console.
734
+ * capability to modify any console, not just the fg_console.
349735 */
350736 int vt_ioctl(struct tty_struct *tty,
351737 unsigned int cmd, unsigned long arg)
352738 {
353739 struct vc_data *vc = tty->driver_data;
354
- struct console_font_op op; /* used in multiple places here */
355
- unsigned int console = vc->vc_num;
356
- unsigned char ucval;
357
- unsigned int uival;
358740 void __user *up = (void __user *)arg;
359741 int i, perm;
360
- int ret = 0;
742
+ int ret;
361743
362744 /*
363745 * To have permissions to do most of the vt ioctls, we either have
....@@ -366,255 +748,29 @@
366748 perm = 0;
367749 if (current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG))
368750 perm = 1;
369
-
751
+
752
+ ret = vt_k_ioctl(tty, cmd, arg, perm);
753
+ if (ret != -ENOIOCTLCMD)
754
+ return ret;
755
+
756
+ ret = vt_io_ioctl(vc, cmd, up, perm);
757
+ if (ret != -ENOIOCTLCMD)
758
+ return ret;
759
+
370760 switch (cmd) {
371761 case TIOCLINUX:
372
- ret = tioclinux(tty, arg);
373
- break;
374
- case KIOCSOUND:
375
- 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
- if (arg)
384
- arg = PIT_TICK_RATE / arg;
385
- kd_mksound(arg, 0);
386
- break;
387
-
388
- case KDMKTONE:
389
- 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
- ticks = msecs_to_jiffies((arg >> 16) & 0xffff);
399
- count = ticks ? (arg & 0xffff) : 0;
400
- if (count)
401
- count = PIT_TICK_RATE / count;
402
- kd_mksound(count, ticks);
403
- break;
404
- }
405
-
406
- case KDGKBTYPE:
407
- /*
408
- * this is naïve.
409
- */
410
- ucval = KB_101;
411
- ret = put_user(ucval, (char __user *)arg);
412
- 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
- if (!capable(CAP_SYS_TTY_CONFIG))
450
- return -EPERM;
451
-
452
- if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) {
453
- ret = -EFAULT;
454
- break;
455
- }
456
- ret = kbd_rate(&kbrep);
457
- if (ret)
458
- break;
459
- 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
- if (!perm)
474
- return -EPERM;
475
- 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
- console_lock();
488
- if (vc->vc_mode == (unsigned char) arg) {
489
- console_unlock();
490
- break;
491
- }
492
- vc->vc_mode = (unsigned char) arg;
493
- if (console != fg_console) {
494
- console_unlock();
495
- break;
496
- }
497
- /*
498
- * explicitly blank/unblank the screen if switching modes
499
- */
500
- if (arg == KD_TEXT)
501
- do_unblank_screen(1);
502
- else
503
- do_blank_screen(1);
504
- console_unlock();
505
- break;
506
-
507
- case KDGETMODE:
508
- uival = vc->vc_mode;
509
- goto setint;
510
-
511
- case KDMAPDISP:
512
- case KDUNMAPDISP:
513
- /*
514
- * these work like a combination of mmap and KDENABIO.
515
- * this could be easily finished.
516
- */
517
- ret = -EINVAL;
518
- break;
519
-
520
- case KDSKBMODE:
521
- if (!perm)
522
- return -EPERM;
523
- ret = vt_do_kdskbmode(console, arg);
524
- if (ret == 0)
525
- tty_ldisc_flush(tty);
526
- break;
527
-
528
- case KDGKBMODE:
529
- uival = vt_do_kdgkbmode(console);
530
- ret = put_user(uival, (int __user *)arg);
531
- break;
532
-
533
- /* this could be folded into KDSKBMODE, but for compatibility
534
- reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
535
- case KDSKBMETA:
536
- ret = vt_do_kdskbmeta(console, arg);
537
- break;
538
-
539
- case KDGKBMETA:
540
- /* FIXME: should review whether this is worth locking */
541
- uival = vt_do_kdgkbmeta(console);
542
- setint:
543
- ret = put_user(uival, (int __user *)arg);
544
- break;
545
-
546
- case KDGETKEYCODE:
547
- case KDSETKEYCODE:
548
- if(!capable(CAP_SYS_TTY_CONFIG))
549
- perm = 0;
550
- ret = vt_do_kbkeycode_ioctl(cmd, up, perm);
551
- break;
552
-
553
- case KDGKBENT:
554
- case KDSKBENT:
555
- ret = vt_do_kdsk_ioctl(cmd, up, perm, console);
556
- break;
557
-
558
- case KDGKBSENT:
559
- case KDSKBSENT:
560
- ret = vt_do_kdgkb_ioctl(cmd, up, perm);
561
- break;
562
-
563
- /* Diacritical processing. Handled in keyboard.c as it has
564
- to operate on the keyboard locks and structures */
565
- case KDGKBDIACR:
566
- case KDGKBDIACRUC:
567
- case KDSKBDIACR:
568
- case KDSKBDIACRUC:
569
- ret = vt_do_diacrit(cmd, up, perm);
570
- break;
571
-
572
- /* the ioctls below read/set the flags usually shown in the leds */
573
- /* don't use them - they will go away without warning */
574
- case KDGKBLED:
575
- case KDSKBLED:
576
- case KDGETLED:
577
- case KDSETLED:
578
- ret = vt_do_kdskled(console, cmd, arg, perm);
579
- break;
580
-
581
- /*
582
- * A process can indicate its willingness to accept signals
583
- * generated by pressing an appropriate key combination.
584
- * Thus, one can have a daemon that e.g. spawns a new console
585
- * upon a keypress and then changes to it.
586
- * See also the kbrequest field of inittab(5).
587
- */
588
- case KDSIGACCEPT:
589
- {
590
- if (!perm || !capable(CAP_KILL))
591
- return -EPERM;
592
- if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
593
- ret = -EINVAL;
594
- else {
595
- spin_lock_irq(&vt_spawn_con.lock);
596
- put_pid(vt_spawn_con.pid);
597
- vt_spawn_con.pid = get_pid(task_pid(current));
598
- vt_spawn_con.sig = arg;
599
- spin_unlock_irq(&vt_spawn_con.lock);
600
- }
601
- break;
602
- }
603
-
762
+ return tioclinux(tty, arg);
604763 case VT_SETMODE:
605764 {
606765 struct vt_mode tmp;
607766
608767 if (!perm)
609768 return -EPERM;
610
- if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) {
611
- ret = -EFAULT;
612
- goto out;
613
- }
614
- if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) {
615
- ret = -EINVAL;
616
- goto out;
617
- }
769
+ if (copy_from_user(&tmp, up, sizeof(struct vt_mode)))
770
+ return -EFAULT;
771
+ if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
772
+ return -EINVAL;
773
+
618774 console_lock();
619775 vc->vt_mode = tmp;
620776 /* the frsig is ignored, so we set it to 0 */
....@@ -638,7 +794,7 @@
638794
639795 rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
640796 if (rc)
641
- ret = -EFAULT;
797
+ return -EFAULT;
642798 break;
643799 }
644800
....@@ -653,18 +809,16 @@
653809 unsigned short state, mask;
654810
655811 if (put_user(fg_console + 1, &vtstat->v_active))
656
- ret = -EFAULT;
657
- else {
658
- state = 1; /* /dev/tty0 is always open */
659
- console_lock(); /* required by vt_in_use() */
660
- for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
661
- ++i, mask <<= 1)
662
- if (vt_in_use(i))
663
- state |= mask;
664
- console_unlock();
665
- ret = put_user(state, &vtstat->v_state);
666
- }
667
- break;
812
+ return -EFAULT;
813
+
814
+ state = 1; /* /dev/tty0 is always open */
815
+ console_lock(); /* required by vt_in_use() */
816
+ for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
817
+ ++i, mask <<= 1)
818
+ if (vt_in_use(i))
819
+ state |= mask;
820
+ console_unlock();
821
+ return put_user(state, &vtstat->v_state);
668822 }
669823
670824 /*
....@@ -676,8 +830,8 @@
676830 if (!vt_in_use(i))
677831 break;
678832 console_unlock();
679
- uival = i < MAX_NR_CONSOLES ? (i+1) : -1;
680
- goto setint;
833
+ i = i < MAX_NR_CONSOLES ? (i+1) : -1;
834
+ return put_user(i, (int __user *)arg);
681835
682836 /*
683837 * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
....@@ -688,59 +842,23 @@
688842 if (!perm)
689843 return -EPERM;
690844 if (arg == 0 || arg > MAX_NR_CONSOLES)
691
- ret = -ENXIO;
692
- else {
693
- arg--;
694
- arg = array_index_nospec(arg, MAX_NR_CONSOLES);
695
- console_lock();
696
- ret = vc_allocate(arg);
697
- console_unlock();
698
- if (ret)
699
- break;
700
- set_console(arg);
701
- }
845
+ return -ENXIO;
846
+
847
+ arg--;
848
+ arg = array_index_nospec(arg, MAX_NR_CONSOLES);
849
+ console_lock();
850
+ ret = vc_allocate(arg);
851
+ console_unlock();
852
+ if (ret)
853
+ return ret;
854
+ set_console(arg);
702855 break;
703856
704857 case VT_SETACTIVATE:
705
- {
706
- struct vt_setactivate vsa;
707
-
708858 if (!perm)
709859 return -EPERM;
710860
711
- if (copy_from_user(&vsa, (struct vt_setactivate __user *)arg,
712
- sizeof(struct vt_setactivate))) {
713
- ret = -EFAULT;
714
- goto out;
715
- }
716
- if (vsa.console == 0 || vsa.console > MAX_NR_CONSOLES)
717
- ret = -ENXIO;
718
- else {
719
- vsa.console--;
720
- vsa.console = array_index_nospec(vsa.console,
721
- MAX_NR_CONSOLES);
722
- console_lock();
723
- ret = vc_allocate(vsa.console);
724
- if (ret == 0) {
725
- struct vc_data *nvc;
726
- /* This is safe providing we don't drop the
727
- console sem between vc_allocate and
728
- finishing referencing nvc */
729
- nvc = vc_cons[vsa.console].d;
730
- nvc->vt_mode = vsa.mode;
731
- nvc->vt_mode.frsig = 0;
732
- put_pid(nvc->vt_pid);
733
- nvc->vt_pid = get_pid(task_pid(current));
734
- }
735
- console_unlock();
736
- if (ret)
737
- break;
738
- /* Commence switch and lock */
739
- /* Review set_console locks */
740
- set_console(vsa.console);
741
- }
742
- break;
743
- }
861
+ return vt_setactivate(up);
744862
745863 /*
746864 * wait until the specified VT has been activated
....@@ -749,10 +867,8 @@
749867 if (!perm)
750868 return -EPERM;
751869 if (arg == 0 || arg > MAX_NR_CONSOLES)
752
- ret = -ENXIO;
753
- else
754
- ret = vt_waitactive(arg);
755
- break;
870
+ return -ENXIO;
871
+ return vt_waitactive(arg);
756872
757873 /*
758874 * If a vt is under process control, the kernel will not switch to it
....@@ -769,268 +885,56 @@
769885 return -EPERM;
770886
771887 console_lock();
772
- if (vc->vt_mode.mode != VT_PROCESS) {
773
- console_unlock();
774
- ret = -EINVAL;
775
- break;
776
- }
777
- /*
778
- * Switching-from response
779
- */
780
- if (vc->vt_newvt >= 0) {
781
- if (arg == 0)
782
- /*
783
- * Switch disallowed, so forget we were trying
784
- * to do it.
785
- */
786
- vc->vt_newvt = -1;
787
-
788
- else {
789
- /*
790
- * The current vt has been released, so
791
- * complete the switch.
792
- */
793
- int newvt;
794
- newvt = vc->vt_newvt;
795
- vc->vt_newvt = -1;
796
- ret = vc_allocate(newvt);
797
- if (ret) {
798
- console_unlock();
799
- break;
800
- }
801
- /*
802
- * When we actually do the console switch,
803
- * make sure we are atomic with respect to
804
- * other console switches..
805
- */
806
- complete_change_console(vc_cons[newvt].d);
807
- }
808
- } else {
809
- /*
810
- * Switched-to response
811
- */
812
- /*
813
- * If it's just an ACK, ignore it
814
- */
815
- if (arg != VT_ACKACQ)
816
- ret = -EINVAL;
817
- }
888
+ ret = vt_reldisp(vc, arg);
818889 console_unlock();
819
- break;
890
+
891
+ return ret;
892
+
820893
821894 /*
822895 * Disallocate memory associated to VT (but leave VT1)
823896 */
824897 case VT_DISALLOCATE:
825
- if (arg > MAX_NR_CONSOLES) {
826
- ret = -ENXIO;
827
- break;
828
- }
898
+ if (arg > MAX_NR_CONSOLES)
899
+ return -ENXIO;
900
+
829901 if (arg == 0)
830902 vt_disallocate_all();
831903 else
832
- ret = vt_disallocate(--arg);
904
+ return vt_disallocate(--arg);
833905 break;
834906
835907 case VT_RESIZE:
836908 {
837909 struct vt_sizes __user *vtsizes = up;
838910 struct vc_data *vc;
839
-
840911 ushort ll,cc;
912
+
841913 if (!perm)
842914 return -EPERM;
843915 if (get_user(ll, &vtsizes->v_rows) ||
844916 get_user(cc, &vtsizes->v_cols))
845
- ret = -EFAULT;
846
- else {
847
- console_lock();
848
- for (i = 0; i < MAX_NR_CONSOLES; i++) {
849
- vc = vc_cons[i].d;
917
+ return -EFAULT;
850918
851
- if (vc) {
852
- vc->vc_resize_user = 1;
853
- /* FIXME: review v tty lock */
854
- vc_resize(vc_cons[i].d, cc, ll);
855
- }
919
+ console_lock();
920
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
921
+ vc = vc_cons[i].d;
922
+
923
+ if (vc) {
924
+ vc->vc_resize_user = 1;
925
+ /* FIXME: review v tty lock */
926
+ vc_resize(vc_cons[i].d, cc, ll);
856927 }
857
- console_unlock();
858928 }
929
+ console_unlock();
859930 break;
860931 }
861932
862933 case VT_RESIZEX:
863
- {
864
- struct vt_consize v;
865
- if (!perm)
866
- return -EPERM;
867
- if (copy_from_user(&v, up, sizeof(struct vt_consize)))
868
- return -EFAULT;
869
- /* FIXME: Should check the copies properly */
870
- if (!v.v_vlin)
871
- v.v_vlin = vc->vc_scan_lines;
872
- if (v.v_clin) {
873
- int rows = v.v_vlin/v.v_clin;
874
- if (v.v_rows != rows) {
875
- if (v.v_rows) /* Parameters don't add up */
876
- return -EINVAL;
877
- v.v_rows = rows;
878
- }
879
- }
880
- if (v.v_vcol && v.v_ccol) {
881
- int cols = v.v_vcol/v.v_ccol;
882
- if (v.v_cols != cols) {
883
- if (v.v_cols)
884
- return -EINVAL;
885
- v.v_cols = cols;
886
- }
887
- }
888
-
889
- if (v.v_clin > 32)
890
- return -EINVAL;
891
-
892
- for (i = 0; i < MAX_NR_CONSOLES; i++) {
893
- struct vc_data *vcp;
894
-
895
- if (!vc_cons[i].d)
896
- continue;
897
- console_lock();
898
- vcp = vc_cons[i].d;
899
- if (vcp) {
900
- int ret;
901
- int save_scan_lines = vcp->vc_scan_lines;
902
- int save_cell_height = vcp->vc_cell_height;
903
-
904
- if (v.v_vlin)
905
- vcp->vc_scan_lines = v.v_vlin;
906
- if (v.v_clin)
907
- vcp->vc_cell_height = v.v_clin;
908
- vcp->vc_resize_user = 1;
909
- ret = vc_resize(vcp, v.v_cols, v.v_rows);
910
- if (ret) {
911
- vcp->vc_scan_lines = save_scan_lines;
912
- vcp->vc_cell_height = save_cell_height;
913
- console_unlock();
914
- return ret;
915
- }
916
- }
917
- console_unlock();
918
- }
919
- break;
920
- }
921
-
922
- case PIO_FONT: {
923
- if (!perm)
924
- return -EPERM;
925
- op.op = KD_FONT_OP_SET;
926
- op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
927
- op.width = 8;
928
- op.height = 0;
929
- op.charcount = 256;
930
- op.data = up;
931
- ret = con_font_op(vc, &op);
932
- break;
933
- }
934
-
935
- case GIO_FONT: {
936
- op.op = KD_FONT_OP_GET;
937
- op.flags = KD_FONT_FLAG_OLD;
938
- op.width = 8;
939
- op.height = 32;
940
- op.charcount = 256;
941
- op.data = up;
942
- ret = con_font_op(vc, &op);
943
- break;
944
- }
945
-
946
- case PIO_CMAP:
947
- if (!perm)
948
- ret = -EPERM;
949
- else
950
- ret = con_set_cmap(up);
951
- break;
952
-
953
- case GIO_CMAP:
954
- ret = con_get_cmap(up);
955
- break;
956
-
957
- case PIO_FONTX:
958
- case GIO_FONTX:
959
- ret = do_fontx_ioctl(vc, cmd, up, perm, &op);
960
- break;
961
-
962
- case PIO_FONTRESET:
963
- {
964934 if (!perm)
965935 return -EPERM;
966936
967
-#ifdef BROKEN_GRAPHICS_PROGRAMS
968
- /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
969
- font is not saved. */
970
- ret = -ENOSYS;
971
- break;
972
-#else
973
- {
974
- op.op = KD_FONT_OP_SET_DEFAULT;
975
- op.data = NULL;
976
- ret = con_font_op(vc, &op);
977
- if (ret)
978
- break;
979
- console_lock();
980
- con_set_default_unimap(vc);
981
- console_unlock();
982
- break;
983
- }
984
-#endif
985
- }
986
-
987
- case KDFONTOP: {
988
- if (copy_from_user(&op, up, sizeof(op))) {
989
- ret = -EFAULT;
990
- break;
991
- }
992
- if (!perm && op.op != KD_FONT_OP_GET)
993
- return -EPERM;
994
- ret = con_font_op(vc, &op);
995
- if (ret)
996
- break;
997
- if (copy_to_user(up, &op, sizeof(op)))
998
- ret = -EFAULT;
999
- break;
1000
- }
1001
-
1002
- case PIO_SCRNMAP:
1003
- if (!perm)
1004
- ret = -EPERM;
1005
- else
1006
- ret = con_set_trans_old(up);
1007
- break;
1008
-
1009
- case GIO_SCRNMAP:
1010
- ret = con_get_trans_old(up);
1011
- break;
1012
-
1013
- case PIO_UNISCRNMAP:
1014
- if (!perm)
1015
- ret = -EPERM;
1016
- else
1017
- ret = con_set_trans_new(up);
1018
- break;
1019
-
1020
- case GIO_UNISCRNMAP:
1021
- ret = con_get_trans_new(up);
1022
- break;
1023
-
1024
- case PIO_UNIMAPCLR:
1025
- if (!perm)
1026
- return -EPERM;
1027
- con_clear_unimap(vc);
1028
- break;
1029
-
1030
- case PIO_UNIMAP:
1031
- case GIO_UNIMAP:
1032
- ret = do_unimap_ioctl(cmd, up, perm, vc);
1033
- break;
937
+ return vt_resizex(vc, up);
1034938
1035939 case VT_LOCKSWITCH:
1036940 if (!capable(CAP_SYS_TTY_CONFIG))
....@@ -1043,17 +947,15 @@
1043947 vt_dont_switch = false;
1044948 break;
1045949 case VT_GETHIFONTMASK:
1046
- ret = put_user(vc->vc_hi_font_mask,
950
+ return put_user(vc->vc_hi_font_mask,
1047951 (unsigned short __user *)arg);
1048
- break;
1049952 case VT_WAITEVENT:
1050
- ret = vt_event_wait_ioctl((struct vt_event __user *)arg);
1051
- break;
953
+ return vt_event_wait_ioctl((struct vt_event __user *)arg);
1052954 default:
1053
- ret = -ENOIOCTLCMD;
955
+ return -ENOIOCTLCMD;
1054956 }
1055
-out:
1056
- return ret;
957
+
958
+ return 0;
1057959 }
1058960
1059961 void reset_vc(struct vc_data *vc)
....@@ -1096,54 +998,6 @@
1096998 }
1097999
10981000 #ifdef CONFIG_COMPAT
1099
-
1100
-struct compat_consolefontdesc {
1101
- unsigned short charcount; /* characters in font (256 or 512) */
1102
- unsigned short charheight; /* scan lines per character (1-32) */
1103
- compat_caddr_t chardata; /* font data in expanded form */
1104
-};
1105
-
1106
-static inline int
1107
-compat_fontx_ioctl(struct vc_data *vc, int cmd,
1108
- struct compat_consolefontdesc __user *user_cfd,
1109
- int perm, struct console_font_op *op)
1110
-{
1111
- struct compat_consolefontdesc cfdarg;
1112
- int i;
1113
-
1114
- if (copy_from_user(&cfdarg, user_cfd, sizeof(struct compat_consolefontdesc)))
1115
- return -EFAULT;
1116
-
1117
- switch (cmd) {
1118
- case PIO_FONTX:
1119
- if (!perm)
1120
- return -EPERM;
1121
- op->op = KD_FONT_OP_SET;
1122
- op->flags = KD_FONT_FLAG_OLD;
1123
- op->width = 8;
1124
- op->height = cfdarg.charheight;
1125
- op->charcount = cfdarg.charcount;
1126
- op->data = compat_ptr(cfdarg.chardata);
1127
- return con_font_op(vc, op);
1128
-
1129
- case GIO_FONTX:
1130
- op->op = KD_FONT_OP_GET;
1131
- op->flags = KD_FONT_FLAG_OLD;
1132
- op->width = 8;
1133
- op->height = cfdarg.charheight;
1134
- op->charcount = cfdarg.charcount;
1135
- op->data = compat_ptr(cfdarg.chardata);
1136
- i = con_font_op(vc, op);
1137
- if (i)
1138
- return i;
1139
- cfdarg.charheight = op->height;
1140
- cfdarg.charcount = op->charcount;
1141
- if (copy_to_user(user_cfd, &cfdarg, sizeof(struct compat_consolefontdesc)))
1142
- return -EFAULT;
1143
- return 0;
1144
- }
1145
- return -EINVAL;
1146
-}
11471001
11481002 struct compat_console_font_op {
11491003 compat_uint_t op; /* operation code KD_FONT_OP_* */
....@@ -1206,9 +1060,8 @@
12061060 {
12071061 struct vc_data *vc = tty->driver_data;
12081062 struct console_font_op op; /* used in multiple places here */
1209
- void __user *up = (void __user *)arg;
1063
+ void __user *up = compat_ptr(arg);
12101064 int perm;
1211
- int ret = 0;
12121065
12131066 /*
12141067 * To have permissions to do most of the vt ioctls, we either have
....@@ -1222,19 +1075,13 @@
12221075 /*
12231076 * these need special handlers for incompatible data structures
12241077 */
1225
- case PIO_FONTX:
1226
- case GIO_FONTX:
1227
- ret = compat_fontx_ioctl(vc, cmd, up, perm, &op);
1228
- break;
12291078
12301079 case KDFONTOP:
1231
- ret = compat_kdfontop_ioctl(up, perm, &op, vc);
1232
- break;
1080
+ return compat_kdfontop_ioctl(up, perm, &op, vc);
12331081
12341082 case PIO_UNIMAP:
12351083 case GIO_UNIMAP:
1236
- ret = compat_unimap_ioctl(cmd, up, perm, vc);
1237
- break;
1084
+ return compat_unimap_ioctl(cmd, up, perm, vc);
12381085
12391086 /*
12401087 * all these treat 'arg' as an integer
....@@ -1259,21 +1106,15 @@
12591106 case VT_DISALLOCATE:
12601107 case VT_RESIZE:
12611108 case VT_RESIZEX:
1262
- goto fallback;
1109
+ return vt_ioctl(tty, cmd, arg);
12631110
12641111 /*
12651112 * the rest has a compatible data structure behind arg,
12661113 * but we have to convert it to a proper 64 bit pointer.
12671114 */
12681115 default:
1269
- arg = (unsigned long)compat_ptr(arg);
1270
- goto fallback;
1116
+ return vt_ioctl(tty, cmd, (unsigned long)up);
12711117 }
1272
-
1273
- return ret;
1274
-
1275
-fallback:
1276
- return vt_ioctl(tty, cmd, arg);
12771118 }
12781119
12791120