diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2018-09-12 11:28:34 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2018-10-13 00:50:44 -0400 |
commit | 77654350306accb55efa73eaa2b1424a639595fc (patch) | |
tree | 5994f7b25de329b258e257f3b19203ec7f3c8199 | |
parent | f82fc0fedf28ba09b0abd0533202447846d48fb9 (diff) |
take compat TIOC[SG]SERIAL treatment into tty_compat_ioctl()
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | drivers/tty/tty_io.c | 81 | ||||
-rw-r--r-- | fs/compat_ioctl.c | 67 |
2 files changed, 81 insertions, 67 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 15d60ba13187..ccc0055b2dfc 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -2651,6 +2651,81 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
2651 | } | 2651 | } |
2652 | 2652 | ||
2653 | #ifdef CONFIG_COMPAT | 2653 | #ifdef CONFIG_COMPAT |
2654 | |||
2655 | struct serial_struct32 { | ||
2656 | compat_int_t type; | ||
2657 | compat_int_t line; | ||
2658 | compat_uint_t port; | ||
2659 | compat_int_t irq; | ||
2660 | compat_int_t flags; | ||
2661 | compat_int_t xmit_fifo_size; | ||
2662 | compat_int_t custom_divisor; | ||
2663 | compat_int_t baud_base; | ||
2664 | unsigned short close_delay; | ||
2665 | char io_type; | ||
2666 | char reserved_char[1]; | ||
2667 | compat_int_t hub6; | ||
2668 | unsigned short closing_wait; /* time to wait before closing */ | ||
2669 | unsigned short closing_wait2; /* no longer used... */ | ||
2670 | compat_uint_t iomem_base; | ||
2671 | unsigned short iomem_reg_shift; | ||
2672 | unsigned int port_high; | ||
2673 | /* compat_ulong_t iomap_base FIXME */ | ||
2674 | compat_int_t reserved[1]; | ||
2675 | }; | ||
2676 | |||
2677 | static int compat_tty_tiocsserial(struct tty_struct *tty, | ||
2678 | struct serial_struct32 __user *ss) | ||
2679 | { | ||
2680 | static DEFINE_RATELIMIT_STATE(depr_flags, | ||
2681 | DEFAULT_RATELIMIT_INTERVAL, | ||
2682 | DEFAULT_RATELIMIT_BURST); | ||
2683 | char comm[TASK_COMM_LEN]; | ||
2684 | struct serial_struct32 v32; | ||
2685 | struct serial_struct v; | ||
2686 | int flags; | ||
2687 | |||
2688 | if (copy_from_user(&v32, ss, sizeof(struct serial_struct32))) | ||
2689 | return -EFAULT; | ||
2690 | |||
2691 | memcpy(&v, &v32, offsetof(struct serial_struct32, iomem_base)); | ||
2692 | v.iomem_base = compat_ptr(v32.iomem_base); | ||
2693 | v.iomem_reg_shift = v32.iomem_reg_shift; | ||
2694 | v.port_high = v32.port_high; | ||
2695 | v.iomap_base = 0; | ||
2696 | |||
2697 | flags = v.flags & ASYNC_DEPRECATED; | ||
2698 | |||
2699 | if (flags && __ratelimit(&depr_flags)) | ||
2700 | pr_warn("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n", | ||
2701 | __func__, get_task_comm(comm, current), flags); | ||
2702 | if (!tty->ops->set_serial) | ||
2703 | return -ENOTTY; | ||
2704 | return tty->ops->set_serial(tty, &v); | ||
2705 | } | ||
2706 | |||
2707 | static int compat_tty_tiocgserial(struct tty_struct *tty, | ||
2708 | struct serial_struct32 __user *ss) | ||
2709 | { | ||
2710 | struct serial_struct32 v32; | ||
2711 | struct serial_struct v; | ||
2712 | int err; | ||
2713 | memset(&v, 0, sizeof(struct serial_struct)); | ||
2714 | |||
2715 | if (!tty->ops->set_serial) | ||
2716 | return -ENOTTY; | ||
2717 | err = tty->ops->get_serial(tty, &v); | ||
2718 | if (!err) { | ||
2719 | memcpy(&v32, &v, offsetof(struct serial_struct32, iomem_base)); | ||
2720 | v32.iomem_base = (unsigned long)v.iomem_base >> 32 ? | ||
2721 | 0xfffffff : ptr_to_compat(v.iomem_base); | ||
2722 | v32.iomem_reg_shift = v.iomem_reg_shift; | ||
2723 | v32.port_high = v.port_high; | ||
2724 | if (copy_to_user(ss, &v32, sizeof(struct serial_struct32))) | ||
2725 | err = -EFAULT; | ||
2726 | } | ||
2727 | return err; | ||
2728 | } | ||
2654 | static long tty_compat_ioctl(struct file *file, unsigned int cmd, | 2729 | static long tty_compat_ioctl(struct file *file, unsigned int cmd, |
2655 | unsigned long arg) | 2730 | unsigned long arg) |
2656 | { | 2731 | { |
@@ -2736,6 +2811,12 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, | |||
2736 | if (tty_paranoia_check(tty, file_inode(file), "tty_ioctl")) | 2811 | if (tty_paranoia_check(tty, file_inode(file), "tty_ioctl")) |
2737 | return -EINVAL; | 2812 | return -EINVAL; |
2738 | 2813 | ||
2814 | switch (cmd) { | ||
2815 | case TIOCSSERIAL: | ||
2816 | return compat_tty_tiocsserial(tty, compat_ptr(arg)); | ||
2817 | case TIOCGSERIAL: | ||
2818 | return compat_tty_tiocgserial(tty, compat_ptr(arg)); | ||
2819 | } | ||
2739 | if (tty->ops->compat_ioctl) { | 2820 | if (tty->ops->compat_ioctl) { |
2740 | retval = tty->ops->compat_ioctl(tty, cmd, arg); | 2821 | retval = tty->ops->compat_ioctl(tty, cmd, arg); |
2741 | if (retval != -ENOIOCTLCMD) | 2822 | if (retval != -ENOIOCTLCMD) |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 670b8cbd0896..2b35c6707e3d 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -560,69 +560,6 @@ static int mt_ioctl_trans(struct file *file, | |||
560 | #define HIDPGETCONNLIST _IOR('H', 210, int) | 560 | #define HIDPGETCONNLIST _IOR('H', 210, int) |
561 | #define HIDPGETCONNINFO _IOR('H', 211, int) | 561 | #define HIDPGETCONNINFO _IOR('H', 211, int) |
562 | 562 | ||
563 | |||
564 | struct serial_struct32 { | ||
565 | compat_int_t type; | ||
566 | compat_int_t line; | ||
567 | compat_uint_t port; | ||
568 | compat_int_t irq; | ||
569 | compat_int_t flags; | ||
570 | compat_int_t xmit_fifo_size; | ||
571 | compat_int_t custom_divisor; | ||
572 | compat_int_t baud_base; | ||
573 | unsigned short close_delay; | ||
574 | char io_type; | ||
575 | char reserved_char[1]; | ||
576 | compat_int_t hub6; | ||
577 | unsigned short closing_wait; /* time to wait before closing */ | ||
578 | unsigned short closing_wait2; /* no longer used... */ | ||
579 | compat_uint_t iomem_base; | ||
580 | unsigned short iomem_reg_shift; | ||
581 | unsigned int port_high; | ||
582 | /* compat_ulong_t iomap_base FIXME */ | ||
583 | compat_int_t reserved[1]; | ||
584 | }; | ||
585 | |||
586 | static int serial_struct_ioctl(struct file *file, | ||
587 | unsigned cmd, struct serial_struct32 __user *ss32) | ||
588 | { | ||
589 | typedef struct serial_struct32 SS32; | ||
590 | int err; | ||
591 | struct serial_struct __user *ss = compat_alloc_user_space(sizeof(*ss)); | ||
592 | __u32 udata; | ||
593 | unsigned int base; | ||
594 | unsigned char *iomem_base; | ||
595 | |||
596 | if (ss == NULL) | ||
597 | return -EFAULT; | ||
598 | if (cmd == TIOCSSERIAL) { | ||
599 | if (copy_in_user(ss, ss32, offsetof(SS32, iomem_base)) || | ||
600 | get_user(udata, &ss32->iomem_base)) | ||
601 | return -EFAULT; | ||
602 | iomem_base = compat_ptr(udata); | ||
603 | if (put_user(iomem_base, &ss->iomem_base) || | ||
604 | convert_in_user(&ss32->iomem_reg_shift, | ||
605 | &ss->iomem_reg_shift) || | ||
606 | convert_in_user(&ss32->port_high, &ss->port_high) || | ||
607 | put_user(0UL, &ss->iomap_base)) | ||
608 | return -EFAULT; | ||
609 | } | ||
610 | err = do_ioctl(file, cmd, (unsigned long)ss); | ||
611 | if (cmd == TIOCGSERIAL && err >= 0) { | ||
612 | if (copy_in_user(ss32, ss, offsetof(SS32, iomem_base)) || | ||
613 | get_user(iomem_base, &ss->iomem_base)) | ||
614 | return -EFAULT; | ||
615 | base = (unsigned long)iomem_base >> 32 ? | ||
616 | 0xffffffff : (unsigned)(unsigned long)iomem_base; | ||
617 | if (put_user(base, &ss32->iomem_base) || | ||
618 | convert_in_user(&ss->iomem_reg_shift, | ||
619 | &ss32->iomem_reg_shift) || | ||
620 | convert_in_user(&ss->port_high, &ss32->port_high)) | ||
621 | return -EFAULT; | ||
622 | } | ||
623 | return err; | ||
624 | } | ||
625 | |||
626 | #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) | 563 | #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) |
627 | #define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) | 564 | #define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) |
628 | #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) | 565 | #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) |
@@ -1242,10 +1179,6 @@ static long do_ioctl_trans(unsigned int cmd, | |||
1242 | case MTIOCPOS32: | 1179 | case MTIOCPOS32: |
1243 | return mt_ioctl_trans(file, cmd, argp); | 1180 | return mt_ioctl_trans(file, cmd, argp); |
1244 | #endif | 1181 | #endif |
1245 | /* Serial */ | ||
1246 | case TIOCGSERIAL: | ||
1247 | case TIOCSSERIAL: | ||
1248 | return serial_struct_ioctl(file, cmd, argp); | ||
1249 | /* Not implemented in the native kernel */ | 1182 | /* Not implemented in the native kernel */ |
1250 | case RTC_IRQP_READ32: | 1183 | case RTC_IRQP_READ32: |
1251 | case RTC_IRQP_SET32: | 1184 | case RTC_IRQP_SET32: |