aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2008-04-30 03:53:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:29:40 -0400
commit9cc3c22bf017f33612748aeb466fdc3695fb1e1d (patch)
tree1143ff2cc5794be68b761ae0e3ebf9747f7fc6c3
parentdd9a451aad4fd7d5f46d2300c0e4fb70d8914453 (diff)
vt_ioctl: Prepare for BKL push down
This one could do with some eyeballs on it. In theory it simply wraps the ioctl handler in lock/unlock_kernel ready for the lock/unlocks to be pushed into specific switch values. To do that means changing the code to return via a common exit path not all over the place as it does now, hence the big diff Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/char/vt_ioctl.c452
1 files changed, 268 insertions, 184 deletions
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index e6f89e8b9258..3211afd9d57e 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -373,11 +373,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
373 unsigned char ucval; 373 unsigned char ucval;
374 void __user *up = (void __user *)arg; 374 void __user *up = (void __user *)arg;
375 int i, perm; 375 int i, perm;
376 376 int ret = 0;
377
377 console = vc->vc_num; 378 console = vc->vc_num;
378 379
379 if (!vc_cons_allocated(console)) /* impossible? */ 380 lock_kernel();
380 return -ENOIOCTLCMD; 381
382 if (!vc_cons_allocated(console)) { /* impossible? */
383 ret = -ENOIOCTLCMD;
384 goto out;
385 }
386
381 387
382 /* 388 /*
383 * To have permissions to do most of the vt ioctls, we either have 389 * To have permissions to do most of the vt ioctls, we either have
@@ -391,15 +397,15 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
391 switch (cmd) { 397 switch (cmd) {
392 case KIOCSOUND: 398 case KIOCSOUND:
393 if (!perm) 399 if (!perm)
394 return -EPERM; 400 goto eperm;
395 if (arg) 401 if (arg)
396 arg = CLOCK_TICK_RATE / arg; 402 arg = CLOCK_TICK_RATE / arg;
397 kd_mksound(arg, 0); 403 kd_mksound(arg, 0);
398 return 0; 404 break;
399 405
400 case KDMKTONE: 406 case KDMKTONE:
401 if (!perm) 407 if (!perm)
402 return -EPERM; 408 goto eperm;
403 { 409 {
404 unsigned int ticks, count; 410 unsigned int ticks, count;
405 411
@@ -412,7 +418,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
412 if (count) 418 if (count)
413 count = CLOCK_TICK_RATE / count; 419 count = CLOCK_TICK_RATE / count;
414 kd_mksound(count, ticks); 420 kd_mksound(count, ticks);
415 return 0; 421 break;
416 } 422 }
417 423
418 case KDGKBTYPE: 424 case KDGKBTYPE:
@@ -435,14 +441,18 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
435 * KDADDIO and KDDELIO may be able to add ports beyond what 441 * KDADDIO and KDDELIO may be able to add ports beyond what
436 * we reject here, but to be safe... 442 * we reject here, but to be safe...
437 */ 443 */
438 if (arg < GPFIRST || arg > GPLAST) 444 if (arg < GPFIRST || arg > GPLAST) {
439 return -EINVAL; 445 ret = -EINVAL;
440 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0; 446 break;
447 }
448 ret = sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
449 break;
441 450
442 case KDENABIO: 451 case KDENABIO:
443 case KDDISABIO: 452 case KDDISABIO:
444 return sys_ioperm(GPFIRST, GPNUM, 453 ret = sys_ioperm(GPFIRST, GPNUM,
445 (cmd == KDENABIO)) ? -ENXIO : 0; 454 (cmd == KDENABIO)) ? -ENXIO : 0;
455 break;
446#endif 456#endif
447 457
448 /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */ 458 /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
@@ -450,19 +460,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
450 case KDKBDREP: 460 case KDKBDREP:
451 { 461 {
452 struct kbd_repeat kbrep; 462 struct kbd_repeat kbrep;
453 int err;
454 463
455 if (!capable(CAP_SYS_TTY_CONFIG)) 464 if (!capable(CAP_SYS_TTY_CONFIG))
456 return -EPERM; 465 goto eperm;
457 466
458 if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) 467 if (copy_from_user(&kbrep, up, sizeof(struct kbd_repeat))) {
459 return -EFAULT; 468 ret = -EFAULT;
460 err = kbd_rate(&kbrep); 469 break;
461 if (err) 470 }
462 return err; 471 ret = kbd_rate(&kbrep);
472 if (ret)
473 break;
463 if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat))) 474 if (copy_to_user(up, &kbrep, sizeof(struct kbd_repeat)))
464 return -EFAULT; 475 ret = -EFAULT;
465 return 0; 476 break;
466 } 477 }
467 478
468 case KDSETMODE: 479 case KDSETMODE:
@@ -475,7 +486,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
475 * need to restore their engine state. --BenH 486 * need to restore their engine state. --BenH
476 */ 487 */
477 if (!perm) 488 if (!perm)
478 return -EPERM; 489 goto eperm;
479 switch (arg) { 490 switch (arg) {
480 case KD_GRAPHICS: 491 case KD_GRAPHICS:
481 break; 492 break;
@@ -485,13 +496,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
485 case KD_TEXT: 496 case KD_TEXT:
486 break; 497 break;
487 default: 498 default:
488 return -EINVAL; 499 ret = -EINVAL;
500 goto out;
489 } 501 }
490 if (vc->vc_mode == (unsigned char) arg) 502 if (vc->vc_mode == (unsigned char) arg)
491 return 0; 503 break;
492 vc->vc_mode = (unsigned char) arg; 504 vc->vc_mode = (unsigned char) arg;
493 if (console != fg_console) 505 if (console != fg_console)
494 return 0; 506 break;
495 /* 507 /*
496 * explicitly blank/unblank the screen if switching modes 508 * explicitly blank/unblank the screen if switching modes
497 */ 509 */
@@ -501,7 +513,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
501 else 513 else
502 do_blank_screen(1); 514 do_blank_screen(1);
503 release_console_sem(); 515 release_console_sem();
504 return 0; 516 break;
505 517
506 case KDGETMODE: 518 case KDGETMODE:
507 ucval = vc->vc_mode; 519 ucval = vc->vc_mode;
@@ -513,11 +525,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
513 * these work like a combination of mmap and KDENABIO. 525 * these work like a combination of mmap and KDENABIO.
514 * this could be easily finished. 526 * this could be easily finished.
515 */ 527 */
516 return -EINVAL; 528 ret = -EINVAL;
529 break;
517 530
518 case KDSKBMODE: 531 case KDSKBMODE:
519 if (!perm) 532 if (!perm)
520 return -EPERM; 533 goto eperm;
521 switch(arg) { 534 switch(arg) {
522 case K_RAW: 535 case K_RAW:
523 kbd->kbdmode = VC_RAW; 536 kbd->kbdmode = VC_RAW;
@@ -534,10 +547,11 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
534 compute_shiftstate(); 547 compute_shiftstate();
535 break; 548 break;
536 default: 549 default:
537 return -EINVAL; 550 ret = -EINVAL;
551 goto out;
538 } 552 }
539 tty_ldisc_flush(tty); 553 tty_ldisc_flush(tty);
540 return 0; 554 break;
541 555
542 case KDGKBMODE: 556 case KDGKBMODE:
543 ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW : 557 ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
@@ -557,28 +571,32 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
557 set_vc_kbd_mode(kbd, VC_META); 571 set_vc_kbd_mode(kbd, VC_META);
558 break; 572 break;
559 default: 573 default:
560 return -EINVAL; 574 ret = -EINVAL;
561 } 575 }
562 return 0; 576 break;
563 577
564 case KDGKBMETA: 578 case KDGKBMETA:
565 ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT); 579 ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
566 setint: 580 setint:
567 return put_user(ucval, (int __user *)arg); 581 ret = put_user(ucval, (int __user *)arg);
582 break;
568 583
569 case KDGETKEYCODE: 584 case KDGETKEYCODE:
570 case KDSETKEYCODE: 585 case KDSETKEYCODE:
571 if(!capable(CAP_SYS_TTY_CONFIG)) 586 if(!capable(CAP_SYS_TTY_CONFIG))
572 perm=0; 587 perm = 0;
573 return do_kbkeycode_ioctl(cmd, up, perm); 588 ret = do_kbkeycode_ioctl(cmd, up, perm);
589 break;
574 590
575 case KDGKBENT: 591 case KDGKBENT:
576 case KDSKBENT: 592 case KDSKBENT:
577 return do_kdsk_ioctl(cmd, up, perm, kbd); 593 ret = do_kdsk_ioctl(cmd, up, perm, kbd);
594 break;
578 595
579 case KDGKBSENT: 596 case KDGKBSENT:
580 case KDSKBSENT: 597 case KDSKBSENT:
581 return do_kdgkb_ioctl(cmd, up, perm); 598 ret = do_kdgkb_ioctl(cmd, up, perm);
599 break;
582 600
583 case KDGKBDIACR: 601 case KDGKBDIACR:
584 { 602 {
@@ -586,26 +604,31 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
586 struct kbdiacr diacr; 604 struct kbdiacr diacr;
587 int i; 605 int i;
588 606
589 if (put_user(accent_table_size, &a->kb_cnt)) 607 if (put_user(accent_table_size, &a->kb_cnt)) {
590 return -EFAULT; 608 ret = -EFAULT;
609 break;
610 }
591 for (i = 0; i < accent_table_size; i++) { 611 for (i = 0; i < accent_table_size; i++) {
592 diacr.diacr = conv_uni_to_8bit(accent_table[i].diacr); 612 diacr.diacr = conv_uni_to_8bit(accent_table[i].diacr);
593 diacr.base = conv_uni_to_8bit(accent_table[i].base); 613 diacr.base = conv_uni_to_8bit(accent_table[i].base);
594 diacr.result = conv_uni_to_8bit(accent_table[i].result); 614 diacr.result = conv_uni_to_8bit(accent_table[i].result);
595 if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr))) 615 if (copy_to_user(a->kbdiacr + i, &diacr, sizeof(struct kbdiacr))) {
596 return -EFAULT; 616 ret = -EFAULT;
617 break;
618 }
597 } 619 }
598 return 0; 620 break;
599 } 621 }
600 case KDGKBDIACRUC: 622 case KDGKBDIACRUC:
601 { 623 {
602 struct kbdiacrsuc __user *a = up; 624 struct kbdiacrsuc __user *a = up;
603 625
604 if (put_user(accent_table_size, &a->kb_cnt)) 626 if (put_user(accent_table_size, &a->kb_cnt))
605 return -EFAULT; 627 ret = -EFAULT;
606 if (copy_to_user(a->kbdiacruc, accent_table, accent_table_size*sizeof(struct kbdiacruc))) 628 else if (copy_to_user(a->kbdiacruc, accent_table,
607 return -EFAULT; 629 accent_table_size*sizeof(struct kbdiacruc)))
608 return 0; 630 ret = -EFAULT;
631 break;
609 } 632 }
610 633
611 case KDSKBDIACR: 634 case KDSKBDIACR:
@@ -616,20 +639,26 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
616 int i; 639 int i;
617 640
618 if (!perm) 641 if (!perm)
619 return -EPERM; 642 goto eperm;
620 if (get_user(ct,&a->kb_cnt)) 643 if (get_user(ct,&a->kb_cnt)) {
621 return -EFAULT; 644 ret = -EFAULT;
622 if (ct >= MAX_DIACR) 645 break;
623 return -EINVAL; 646 }
647 if (ct >= MAX_DIACR) {
648 ret = -EINVAL;
649 break;
650 }
624 accent_table_size = ct; 651 accent_table_size = ct;
625 for (i = 0; i < ct; i++) { 652 for (i = 0; i < ct; i++) {
626 if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr))) 653 if (copy_from_user(&diacr, a->kbdiacr + i, sizeof(struct kbdiacr))) {
627 return -EFAULT; 654 ret = -EFAULT;
655 break;
656 }
628 accent_table[i].diacr = conv_8bit_to_uni(diacr.diacr); 657 accent_table[i].diacr = conv_8bit_to_uni(diacr.diacr);
629 accent_table[i].base = conv_8bit_to_uni(diacr.base); 658 accent_table[i].base = conv_8bit_to_uni(diacr.base);
630 accent_table[i].result = conv_8bit_to_uni(diacr.result); 659 accent_table[i].result = conv_8bit_to_uni(diacr.result);
631 } 660 }
632 return 0; 661 break;
633 } 662 }
634 663
635 case KDSKBDIACRUC: 664 case KDSKBDIACRUC:
@@ -638,15 +667,19 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
638 unsigned int ct; 667 unsigned int ct;
639 668
640 if (!perm) 669 if (!perm)
641 return -EPERM; 670 goto eperm;
642 if (get_user(ct,&a->kb_cnt)) 671 if (get_user(ct,&a->kb_cnt)) {
643 return -EFAULT; 672 ret = -EFAULT;
644 if (ct >= MAX_DIACR) 673 break;
645 return -EINVAL; 674 }
675 if (ct >= MAX_DIACR) {
676 ret = -EINVAL;
677 break;
678 }
646 accent_table_size = ct; 679 accent_table_size = ct;
647 if (copy_from_user(accent_table, a->kbdiacruc, ct*sizeof(struct kbdiacruc))) 680 if (copy_from_user(accent_table, a->kbdiacruc, ct*sizeof(struct kbdiacruc)))
648 return -EFAULT; 681 ret = -EFAULT;
649 return 0; 682 break;
650 } 683 }
651 684
652 /* the ioctls below read/set the flags usually shown in the leds */ 685 /* the ioctls below read/set the flags usually shown in the leds */
@@ -657,26 +690,29 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
657 690
658 case KDSKBLED: 691 case KDSKBLED:
659 if (!perm) 692 if (!perm)
660 return -EPERM; 693 goto eperm;
661 if (arg & ~0x77) 694 if (arg & ~0x77) {
662 return -EINVAL; 695 ret = -EINVAL;
696 break;
697 }
663 kbd->ledflagstate = (arg & 7); 698 kbd->ledflagstate = (arg & 7);
664 kbd->default_ledflagstate = ((arg >> 4) & 7); 699 kbd->default_ledflagstate = ((arg >> 4) & 7);
665 set_leds(); 700 set_leds();
666 return 0; 701 break;
667 702
668 /* the ioctls below only set the lights, not the functions */ 703 /* the ioctls below only set the lights, not the functions */
669 /* for those, see KDGKBLED and KDSKBLED above */ 704 /* for those, see KDGKBLED and KDSKBLED above */
670 case KDGETLED: 705 case KDGETLED:
671 ucval = getledstate(); 706 ucval = getledstate();
672 setchar: 707 setchar:
673 return put_user(ucval, (char __user *)arg); 708 ret = put_user(ucval, (char __user *)arg);
709 break;
674 710
675 case KDSETLED: 711 case KDSETLED:
676 if (!perm) 712 if (!perm)
677 return -EPERM; 713 goto eperm;
678 setledstate(kbd, arg); 714 setledstate(kbd, arg);
679 return 0; 715 break;
680 716
681 /* 717 /*
682 * A process can indicate its willingness to accept signals 718 * A process can indicate its willingness to accept signals
@@ -688,16 +724,17 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
688 case KDSIGACCEPT: 724 case KDSIGACCEPT:
689 { 725 {
690 if (!perm || !capable(CAP_KILL)) 726 if (!perm || !capable(CAP_KILL))
691 return -EPERM; 727 goto eperm;
692 if (!valid_signal(arg) || arg < 1 || arg == SIGKILL) 728 if (!valid_signal(arg) || arg < 1 || arg == SIGKILL)
693 return -EINVAL; 729 ret = -EINVAL;
694 730 else {
695 spin_lock_irq(&vt_spawn_con.lock); 731 spin_lock_irq(&vt_spawn_con.lock);
696 put_pid(vt_spawn_con.pid); 732 put_pid(vt_spawn_con.pid);
697 vt_spawn_con.pid = get_pid(task_pid(current)); 733 vt_spawn_con.pid = get_pid(task_pid(current));
698 vt_spawn_con.sig = arg; 734 vt_spawn_con.sig = arg;
699 spin_unlock_irq(&vt_spawn_con.lock); 735 spin_unlock_irq(&vt_spawn_con.lock);
700 return 0; 736 }
737 break;
701 } 738 }
702 739
703 case VT_SETMODE: 740 case VT_SETMODE:
@@ -705,11 +742,15 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
705 struct vt_mode tmp; 742 struct vt_mode tmp;
706 743
707 if (!perm) 744 if (!perm)
708 return -EPERM; 745 goto eperm;
709 if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) 746 if (copy_from_user(&tmp, up, sizeof(struct vt_mode))) {
710 return -EFAULT; 747 ret = -EFAULT;
711 if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) 748 goto out;
712 return -EINVAL; 749 }
750 if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS) {
751 ret = -EINVAL;
752 goto out;
753 }
713 acquire_console_sem(); 754 acquire_console_sem();
714 vc->vt_mode = tmp; 755 vc->vt_mode = tmp;
715 /* the frsig is ignored, so we set it to 0 */ 756 /* the frsig is ignored, so we set it to 0 */
@@ -719,7 +760,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
719 /* no switch is required -- saw@shade.msu.ru */ 760 /* no switch is required -- saw@shade.msu.ru */
720 vc->vt_newvt = -1; 761 vc->vt_newvt = -1;
721 release_console_sem(); 762 release_console_sem();
722 return 0; 763 break;
723 } 764 }
724 765
725 case VT_GETMODE: 766 case VT_GETMODE:
@@ -732,7 +773,9 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
732 release_console_sem(); 773 release_console_sem();
733 774
734 rc = copy_to_user(up, &tmp, sizeof(struct vt_mode)); 775 rc = copy_to_user(up, &tmp, sizeof(struct vt_mode));
735 return rc ? -EFAULT : 0; 776 if (rc)
777 ret = -EFAULT;
778 break;
736 } 779 }
737 780
738 /* 781 /*
@@ -746,12 +789,16 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
746 unsigned short state, mask; 789 unsigned short state, mask;
747 790
748 if (put_user(fg_console + 1, &vtstat->v_active)) 791 if (put_user(fg_console + 1, &vtstat->v_active))
749 return -EFAULT; 792 ret = -EFAULT;
750 state = 1; /* /dev/tty0 is always open */ 793 else {
751 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1) 794 state = 1; /* /dev/tty0 is always open */
752 if (VT_IS_IN_USE(i)) 795 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask;
753 state |= mask; 796 ++i, mask <<= 1)
754 return put_user(state, &vtstat->v_state); 797 if (VT_IS_IN_USE(i))
798 state |= mask;
799 ret = put_user(state, &vtstat->v_state);
800 }
801 break;
755 } 802 }
756 803
757 /* 804 /*
@@ -771,27 +818,31 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
771 */ 818 */
772 case VT_ACTIVATE: 819 case VT_ACTIVATE:
773 if (!perm) 820 if (!perm)
774 return -EPERM; 821 goto eperm;
775 if (arg == 0 || arg > MAX_NR_CONSOLES) 822 if (arg == 0 || arg > MAX_NR_CONSOLES)
776 return -ENXIO; 823 ret = -ENXIO;
777 arg--; 824 else {
778 acquire_console_sem(); 825 arg--;
779 i = vc_allocate(arg); 826 acquire_console_sem();
780 release_console_sem(); 827 ret = vc_allocate(arg);
781 if (i) 828 release_console_sem();
782 return i; 829 if (ret)
783 set_console(arg); 830 break;
784 return 0; 831 set_console(arg);
832 }
833 break;
785 834
786 /* 835 /*
787 * wait until the specified VT has been activated 836 * wait until the specified VT has been activated
788 */ 837 */
789 case VT_WAITACTIVE: 838 case VT_WAITACTIVE:
790 if (!perm) 839 if (!perm)
791 return -EPERM; 840 goto eperm;
792 if (arg == 0 || arg > MAX_NR_CONSOLES) 841 if (arg == 0 || arg > MAX_NR_CONSOLES)
793 return -ENXIO; 842 ret = -ENXIO;
794 return vt_waitactive(arg-1); 843 else
844 ret = vt_waitactive(arg - 1);
845 break;
795 846
796 /* 847 /*
797 * If a vt is under process control, the kernel will not switch to it 848 * If a vt is under process control, the kernel will not switch to it
@@ -805,10 +856,12 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
805 */ 856 */
806 case VT_RELDISP: 857 case VT_RELDISP:
807 if (!perm) 858 if (!perm)
808 return -EPERM; 859 goto eperm;
809 if (vc->vt_mode.mode != VT_PROCESS)
810 return -EINVAL;
811 860
861 if (vc->vt_mode.mode != VT_PROCESS) {
862 ret = -EINVAL;
863 break;
864 }
812 /* 865 /*
813 * Switching-from response 866 * Switching-from response
814 */ 867 */
@@ -829,10 +882,10 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
829 int newvt; 882 int newvt;
830 newvt = vc->vt_newvt; 883 newvt = vc->vt_newvt;
831 vc->vt_newvt = -1; 884 vc->vt_newvt = -1;
832 i = vc_allocate(newvt); 885 ret = vc_allocate(newvt);
833 if (i) { 886 if (ret) {
834 release_console_sem(); 887 release_console_sem();
835 return i; 888 break;
836 } 889 }
837 /* 890 /*
838 * When we actually do the console switch, 891 * When we actually do the console switch,
@@ -841,31 +894,27 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
841 */ 894 */
842 complete_change_console(vc_cons[newvt].d); 895 complete_change_console(vc_cons[newvt].d);
843 } 896 }
844 } 897 } else {
845 898 /*
846 /* 899 * Switched-to response
847 * Switched-to response 900 */
848 */
849 else
850 {
851 /* 901 /*
852 * If it's just an ACK, ignore it 902 * If it's just an ACK, ignore it
853 */ 903 */
854 if (arg != VT_ACKACQ) { 904 if (arg != VT_ACKACQ)
855 release_console_sem(); 905 ret = -EINVAL;
856 return -EINVAL;
857 }
858 } 906 }
859 release_console_sem(); 907 release_console_sem();
860 908 break;
861 return 0;
862 909
863 /* 910 /*
864 * Disallocate memory associated to VT (but leave VT1) 911 * Disallocate memory associated to VT (but leave VT1)
865 */ 912 */
866 case VT_DISALLOCATE: 913 case VT_DISALLOCATE:
867 if (arg > MAX_NR_CONSOLES) 914 if (arg > MAX_NR_CONSOLES) {
868 return -ENXIO; 915 ret = -ENXIO;
916 break;
917 }
869 if (arg == 0) { 918 if (arg == 0) {
870 /* deallocate all unused consoles, but leave 0 */ 919 /* deallocate all unused consoles, but leave 0 */
871 acquire_console_sem(); 920 acquire_console_sem();
@@ -877,14 +926,14 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
877 /* deallocate a single console, if possible */ 926 /* deallocate a single console, if possible */
878 arg--; 927 arg--;
879 if (VT_BUSY(arg)) 928 if (VT_BUSY(arg))
880 return -EBUSY; 929 ret = -EBUSY;
881 if (arg) { /* leave 0 */ 930 else if (arg) { /* leave 0 */
882 acquire_console_sem(); 931 acquire_console_sem();
883 vc_deallocate(arg); 932 vc_deallocate(arg);
884 release_console_sem(); 933 release_console_sem();
885 } 934 }
886 } 935 }
887 return 0; 936 break;
888 937
889 case VT_RESIZE: 938 case VT_RESIZE:
890 { 939 {
@@ -893,21 +942,21 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
893 942
894 ushort ll,cc; 943 ushort ll,cc;
895 if (!perm) 944 if (!perm)
896 return -EPERM; 945 goto eperm;
897 if (get_user(ll, &vtsizes->v_rows) || 946 if (get_user(ll, &vtsizes->v_rows) ||
898 get_user(cc, &vtsizes->v_cols)) 947 get_user(cc, &vtsizes->v_cols))
899 return -EFAULT; 948 ret = -EFAULT;
900 949 else {
901 for (i = 0; i < MAX_NR_CONSOLES; i++) { 950 for (i = 0; i < MAX_NR_CONSOLES; i++) {
902 vc = vc_cons[i].d; 951 vc = vc_cons[i].d;
903 952
904 if (vc) { 953 if (vc) {
905 vc->vc_resize_user = 1; 954 vc->vc_resize_user = 1;
906 vc_lock_resize(vc_cons[i].d, cc, ll); 955 vc_lock_resize(vc_cons[i].d, cc, ll);
956 }
907 } 957 }
908 } 958 }
909 959 break;
910 return 0;
911 } 960 }
912 961
913 case VT_RESIZEX: 962 case VT_RESIZEX:
@@ -915,10 +964,13 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
915 struct vt_consize __user *vtconsize = up; 964 struct vt_consize __user *vtconsize = up;
916 ushort ll,cc,vlin,clin,vcol,ccol; 965 ushort ll,cc,vlin,clin,vcol,ccol;
917 if (!perm) 966 if (!perm)
918 return -EPERM; 967 goto eperm;
919 if (!access_ok(VERIFY_READ, vtconsize, 968 if (!access_ok(VERIFY_READ, vtconsize,
920 sizeof(struct vt_consize))) 969 sizeof(struct vt_consize))) {
921 return -EFAULT; 970 ret = -EFAULT;
971 break;
972 }
973 /* FIXME: Should check the copies properly */
922 __get_user(ll, &vtconsize->v_rows); 974 __get_user(ll, &vtconsize->v_rows);
923 __get_user(cc, &vtconsize->v_cols); 975 __get_user(cc, &vtconsize->v_cols);
924 __get_user(vlin, &vtconsize->v_vlin); 976 __get_user(vlin, &vtconsize->v_vlin);
@@ -928,21 +980,28 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
928 vlin = vlin ? vlin : vc->vc_scan_lines; 980 vlin = vlin ? vlin : vc->vc_scan_lines;
929 if (clin) { 981 if (clin) {
930 if (ll) { 982 if (ll) {
931 if (ll != vlin/clin) 983 if (ll != vlin/clin) {
932 return -EINVAL; /* Parameters don't add up */ 984 /* Parameters don't add up */
985 ret = -EINVAL;
986 break;
987 }
933 } else 988 } else
934 ll = vlin/clin; 989 ll = vlin/clin;
935 } 990 }
936 if (vcol && ccol) { 991 if (vcol && ccol) {
937 if (cc) { 992 if (cc) {
938 if (cc != vcol/ccol) 993 if (cc != vcol/ccol) {
939 return -EINVAL; 994 ret = -EINVAL;
995 break;
996 }
940 } else 997 } else
941 cc = vcol/ccol; 998 cc = vcol/ccol;
942 } 999 }
943 1000
944 if (clin > 32) 1001 if (clin > 32) {
945 return -EINVAL; 1002 ret = -EINVAL;
1003 break;
1004 }
946 1005
947 for (i = 0; i < MAX_NR_CONSOLES; i++) { 1006 for (i = 0; i < MAX_NR_CONSOLES; i++) {
948 if (!vc_cons[i].d) 1007 if (!vc_cons[i].d)
@@ -956,19 +1015,20 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
956 vc_resize(vc_cons[i].d, cc, ll); 1015 vc_resize(vc_cons[i].d, cc, ll);
957 release_console_sem(); 1016 release_console_sem();
958 } 1017 }
959 return 0; 1018 break;
960 } 1019 }
961 1020
962 case PIO_FONT: { 1021 case PIO_FONT: {
963 if (!perm) 1022 if (!perm)
964 return -EPERM; 1023 goto eperm;
965 op.op = KD_FONT_OP_SET; 1024 op.op = KD_FONT_OP_SET;
966 op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */ 1025 op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
967 op.width = 8; 1026 op.width = 8;
968 op.height = 0; 1027 op.height = 0;
969 op.charcount = 256; 1028 op.charcount = 256;
970 op.data = up; 1029 op.data = up;
971 return con_font_op(vc_cons[fg_console].d, &op); 1030 ret = con_font_op(vc_cons[fg_console].d, &op);
1031 break;
972 } 1032 }
973 1033
974 case GIO_FONT: { 1034 case GIO_FONT: {
@@ -978,100 +1038,124 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
978 op.height = 32; 1038 op.height = 32;
979 op.charcount = 256; 1039 op.charcount = 256;
980 op.data = up; 1040 op.data = up;
981 return con_font_op(vc_cons[fg_console].d, &op); 1041 ret = con_font_op(vc_cons[fg_console].d, &op);
1042 break;
982 } 1043 }
983 1044
984 case PIO_CMAP: 1045 case PIO_CMAP:
985 if (!perm) 1046 if (!perm)
986 return -EPERM; 1047 ret = -EPERM;
987 return con_set_cmap(up); 1048 else
1049 ret = con_set_cmap(up);
1050 break;
988 1051
989 case GIO_CMAP: 1052 case GIO_CMAP:
990 return con_get_cmap(up); 1053 ret = con_get_cmap(up);
1054 break;
991 1055
992 case PIO_FONTX: 1056 case PIO_FONTX:
993 case GIO_FONTX: 1057 case GIO_FONTX:
994 return do_fontx_ioctl(cmd, up, perm, &op); 1058 ret = do_fontx_ioctl(cmd, up, perm, &op);
1059 break;
995 1060
996 case PIO_FONTRESET: 1061 case PIO_FONTRESET:
997 { 1062 {
998 if (!perm) 1063 if (!perm)
999 return -EPERM; 1064 goto eperm;
1000 1065
1001#ifdef BROKEN_GRAPHICS_PROGRAMS 1066#ifdef BROKEN_GRAPHICS_PROGRAMS
1002 /* With BROKEN_GRAPHICS_PROGRAMS defined, the default 1067 /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
1003 font is not saved. */ 1068 font is not saved. */
1004 return -ENOSYS; 1069 ret = -ENOSYS;
1070 break;
1005#else 1071#else
1006 { 1072 {
1007 op.op = KD_FONT_OP_SET_DEFAULT; 1073 op.op = KD_FONT_OP_SET_DEFAULT;
1008 op.data = NULL; 1074 op.data = NULL;
1009 i = con_font_op(vc_cons[fg_console].d, &op); 1075 ret = con_font_op(vc_cons[fg_console].d, &op);
1010 if (i) 1076 if (ret)
1011 return i; 1077 break;
1012 con_set_default_unimap(vc_cons[fg_console].d); 1078 con_set_default_unimap(vc_cons[fg_console].d);
1013 return 0; 1079 break;
1014 } 1080 }
1015#endif 1081#endif
1016 } 1082 }
1017 1083
1018 case KDFONTOP: { 1084 case KDFONTOP: {
1019 if (copy_from_user(&op, up, sizeof(op))) 1085 if (copy_from_user(&op, up, sizeof(op))) {
1020 return -EFAULT; 1086 ret = -EFAULT;
1087 break;
1088 }
1021 if (!perm && op.op != KD_FONT_OP_GET) 1089 if (!perm && op.op != KD_FONT_OP_GET)
1022 return -EPERM; 1090 goto eperm;
1023 i = con_font_op(vc, &op); 1091 ret = con_font_op(vc, &op);
1024 if (i) return i; 1092 if (ret)
1093 break;
1025 if (copy_to_user(up, &op, sizeof(op))) 1094 if (copy_to_user(up, &op, sizeof(op)))
1026 return -EFAULT; 1095 ret = -EFAULT;
1027 return 0; 1096 break;
1028 } 1097 }
1029 1098
1030 case PIO_SCRNMAP: 1099 case PIO_SCRNMAP:
1031 if (!perm) 1100 if (!perm)
1032 return -EPERM; 1101 ret = -EPERM;
1033 return con_set_trans_old(up); 1102 else
1103 ret = con_set_trans_old(up);
1104 break;
1034 1105
1035 case GIO_SCRNMAP: 1106 case GIO_SCRNMAP:
1036 return con_get_trans_old(up); 1107 ret = con_get_trans_old(up);
1108 break;
1037 1109
1038 case PIO_UNISCRNMAP: 1110 case PIO_UNISCRNMAP:
1039 if (!perm) 1111 if (!perm)
1040 return -EPERM; 1112 ret = -EPERM;
1041 return con_set_trans_new(up); 1113 else
1114 ret = con_set_trans_new(up);
1115 break;
1042 1116
1043 case GIO_UNISCRNMAP: 1117 case GIO_UNISCRNMAP:
1044 return con_get_trans_new(up); 1118 ret = con_get_trans_new(up);
1119 break;
1045 1120
1046 case PIO_UNIMAPCLR: 1121 case PIO_UNIMAPCLR:
1047 { struct unimapinit ui; 1122 { struct unimapinit ui;
1048 if (!perm) 1123 if (!perm)
1049 return -EPERM; 1124 goto eperm;
1050 i = copy_from_user(&ui, up, sizeof(struct unimapinit)); 1125 ret = copy_from_user(&ui, up, sizeof(struct unimapinit));
1051 if (i) return -EFAULT; 1126 if (!ret)
1052 con_clear_unimap(vc, &ui); 1127 con_clear_unimap(vc, &ui);
1053 return 0; 1128 break;
1054 } 1129 }
1055 1130
1056 case PIO_UNIMAP: 1131 case PIO_UNIMAP:
1057 case GIO_UNIMAP: 1132 case GIO_UNIMAP:
1058 return do_unimap_ioctl(cmd, up, perm, vc); 1133 ret = do_unimap_ioctl(cmd, up, perm, vc);
1134 break;
1059 1135
1060 case VT_LOCKSWITCH: 1136 case VT_LOCKSWITCH:
1061 if (!capable(CAP_SYS_TTY_CONFIG)) 1137 if (!capable(CAP_SYS_TTY_CONFIG))
1062 return -EPERM; 1138 goto eperm;
1063 vt_dont_switch = 1; 1139 vt_dont_switch = 1;
1064 return 0; 1140 break;
1065 case VT_UNLOCKSWITCH: 1141 case VT_UNLOCKSWITCH:
1066 if (!capable(CAP_SYS_TTY_CONFIG)) 1142 if (!capable(CAP_SYS_TTY_CONFIG))
1067 return -EPERM; 1143 goto eperm;
1068 vt_dont_switch = 0; 1144 vt_dont_switch = 0;
1069 return 0; 1145 break;
1070 case VT_GETHIFONTMASK: 1146 case VT_GETHIFONTMASK:
1071 return put_user(vc->vc_hi_font_mask, (unsigned short __user *)arg); 1147 ret = put_user(vc->vc_hi_font_mask,
1148 (unsigned short __user *)arg);
1149 break;
1072 default: 1150 default:
1073 return -ENOIOCTLCMD; 1151 ret = -ENOIOCTLCMD;
1074 } 1152 }
1153out:
1154 unlock_kernel();
1155 return ret;
1156eperm:
1157 ret = -EPERM;
1158 goto out;
1075} 1159}
1076 1160
1077/* 1161/*