diff options
author | Alan Cox <alan@lxorguk.ukuu.org.uk> | 2008-04-30 03:53:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-30 11:29:40 -0400 |
commit | 9cc3c22bf017f33612748aeb466fdc3695fb1e1d (patch) | |
tree | 1143ff2cc5794be68b761ae0e3ebf9747f7fc6c3 | |
parent | dd9a451aad4fd7d5f46d2300c0e4fb70d8914453 (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.c | 452 |
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 | } |
1153 | out: | ||
1154 | unlock_kernel(); | ||
1155 | return ret; | ||
1156 | eperm: | ||
1157 | ret = -EPERM; | ||
1158 | goto out; | ||
1075 | } | 1159 | } |
1076 | 1160 | ||
1077 | /* | 1161 | /* |