aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2018-09-12 11:28:34 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2018-10-13 00:50:44 -0400
commit77654350306accb55efa73eaa2b1424a639595fc (patch)
tree5994f7b25de329b258e257f3b19203ec7f3c8199
parentf82fc0fedf28ba09b0abd0533202447846d48fb9 (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.c81
-rw-r--r--fs/compat_ioctl.c67
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
2655struct 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
2677static 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
2707static 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}
2654static long tty_compat_ioctl(struct file *file, unsigned int cmd, 2729static 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
564struct 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
586static 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: