Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alan Cox and committed by
Linus Torvalds
9cc3c22b dd9a451a

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