diff options
-rw-r--r-- | drivers/net/macvtap.c | 44 | ||||
-rw-r--r-- | drivers/net/tun.c | 44 |
2 files changed, 45 insertions, 43 deletions
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 8f8004552d8e..22b4cf2fa108 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -640,12 +640,12 @@ static void macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, | |||
640 | 640 | ||
641 | /* Get packet from user space buffer */ | 641 | /* Get packet from user space buffer */ |
642 | static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | 642 | static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, |
643 | const struct iovec *iv, unsigned long total_len, | 643 | struct iov_iter *from, int noblock) |
644 | size_t count, int noblock) | ||
645 | { | 644 | { |
646 | int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); | 645 | int good_linear = SKB_MAX_HEAD(NET_IP_ALIGN); |
647 | struct sk_buff *skb; | 646 | struct sk_buff *skb; |
648 | struct macvlan_dev *vlan; | 647 | struct macvlan_dev *vlan; |
648 | unsigned long total_len = iov_iter_count(from); | ||
649 | unsigned long len = total_len; | 649 | unsigned long len = total_len; |
650 | int err; | 650 | int err; |
651 | struct virtio_net_hdr vnet_hdr = { 0 }; | 651 | struct virtio_net_hdr vnet_hdr = { 0 }; |
@@ -653,6 +653,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
653 | int copylen = 0; | 653 | int copylen = 0; |
654 | bool zerocopy = false; | 654 | bool zerocopy = false; |
655 | size_t linear; | 655 | size_t linear; |
656 | ssize_t n; | ||
656 | 657 | ||
657 | if (q->flags & IFF_VNET_HDR) { | 658 | if (q->flags & IFF_VNET_HDR) { |
658 | vnet_hdr_len = q->vnet_hdr_sz; | 659 | vnet_hdr_len = q->vnet_hdr_sz; |
@@ -662,10 +663,11 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
662 | goto err; | 663 | goto err; |
663 | len -= vnet_hdr_len; | 664 | len -= vnet_hdr_len; |
664 | 665 | ||
665 | err = memcpy_fromiovecend((void *)&vnet_hdr, iv, 0, | 666 | err = -EFAULT; |
666 | sizeof(vnet_hdr)); | 667 | n = copy_from_iter(&vnet_hdr, sizeof(vnet_hdr), from); |
667 | if (err < 0) | 668 | if (n != sizeof(vnet_hdr)) |
668 | goto err; | 669 | goto err; |
670 | iov_iter_advance(from, vnet_hdr_len - sizeof(vnet_hdr)); | ||
669 | if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && | 671 | if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && |
670 | vnet_hdr.csum_start + vnet_hdr.csum_offset + 2 > | 672 | vnet_hdr.csum_start + vnet_hdr.csum_offset + 2 > |
671 | vnet_hdr.hdr_len) | 673 | vnet_hdr.hdr_len) |
@@ -680,17 +682,16 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
680 | if (unlikely(len < ETH_HLEN)) | 682 | if (unlikely(len < ETH_HLEN)) |
681 | goto err; | 683 | goto err; |
682 | 684 | ||
683 | err = -EMSGSIZE; | ||
684 | if (unlikely(count > UIO_MAXIOV)) | ||
685 | goto err; | ||
686 | |||
687 | if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) { | 685 | if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) { |
686 | struct iov_iter i; | ||
687 | |||
688 | copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN; | 688 | copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN; |
689 | if (copylen > good_linear) | 689 | if (copylen > good_linear) |
690 | copylen = good_linear; | 690 | copylen = good_linear; |
691 | linear = copylen; | 691 | linear = copylen; |
692 | if (iov_pages(iv, vnet_hdr_len + copylen, count) | 692 | i = *from; |
693 | <= MAX_SKB_FRAGS) | 693 | iov_iter_advance(&i, copylen); |
694 | if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS) | ||
694 | zerocopy = true; | 695 | zerocopy = true; |
695 | } | 696 | } |
696 | 697 | ||
@@ -708,10 +709,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
708 | goto err; | 709 | goto err; |
709 | 710 | ||
710 | if (zerocopy) | 711 | if (zerocopy) |
711 | err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count); | 712 | err = zerocopy_sg_from_iter(skb, from); |
712 | else { | 713 | else { |
713 | err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, | 714 | err = skb_copy_datagram_from_iter(skb, 0, from, len); |
714 | len); | ||
715 | if (!err && m && m->msg_control) { | 715 | if (!err && m && m->msg_control) { |
716 | struct ubuf_info *uarg = m->msg_control; | 716 | struct ubuf_info *uarg = m->msg_control; |
717 | uarg->callback(uarg, false); | 717 | uarg->callback(uarg, false); |
@@ -764,16 +764,12 @@ err: | |||
764 | return err; | 764 | return err; |
765 | } | 765 | } |
766 | 766 | ||
767 | static ssize_t macvtap_aio_write(struct kiocb *iocb, const struct iovec *iv, | 767 | static ssize_t macvtap_write_iter(struct kiocb *iocb, struct iov_iter *from) |
768 | unsigned long count, loff_t pos) | ||
769 | { | 768 | { |
770 | struct file *file = iocb->ki_filp; | 769 | struct file *file = iocb->ki_filp; |
771 | ssize_t result = -ENOLINK; | ||
772 | struct macvtap_queue *q = file->private_data; | 770 | struct macvtap_queue *q = file->private_data; |
773 | 771 | ||
774 | result = macvtap_get_user(q, NULL, iv, iov_length(iv, count), count, | 772 | return macvtap_get_user(q, NULL, from, file->f_flags & O_NONBLOCK); |
775 | file->f_flags & O_NONBLOCK); | ||
776 | return result; | ||
777 | } | 773 | } |
778 | 774 | ||
779 | /* Put packet to the user space buffer */ | 775 | /* Put packet to the user space buffer */ |
@@ -1081,8 +1077,9 @@ static const struct file_operations macvtap_fops = { | |||
1081 | .open = macvtap_open, | 1077 | .open = macvtap_open, |
1082 | .release = macvtap_release, | 1078 | .release = macvtap_release, |
1083 | .read = new_sync_read, | 1079 | .read = new_sync_read, |
1080 | .write = new_sync_write, | ||
1084 | .read_iter = macvtap_read_iter, | 1081 | .read_iter = macvtap_read_iter, |
1085 | .aio_write = macvtap_aio_write, | 1082 | .write_iter = macvtap_write_iter, |
1086 | .poll = macvtap_poll, | 1083 | .poll = macvtap_poll, |
1087 | .llseek = no_llseek, | 1084 | .llseek = no_llseek, |
1088 | .unlocked_ioctl = macvtap_ioctl, | 1085 | .unlocked_ioctl = macvtap_ioctl, |
@@ -1095,8 +1092,9 @@ static int macvtap_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1095 | struct msghdr *m, size_t total_len) | 1092 | struct msghdr *m, size_t total_len) |
1096 | { | 1093 | { |
1097 | struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); | 1094 | struct macvtap_queue *q = container_of(sock, struct macvtap_queue, sock); |
1098 | return macvtap_get_user(q, m, m->msg_iov, total_len, m->msg_iovlen, | 1095 | struct iov_iter from; |
1099 | m->msg_flags & MSG_DONTWAIT); | 1096 | iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len); |
1097 | return macvtap_get_user(q, m, &from, m->msg_flags & MSG_DONTWAIT); | ||
1100 | } | 1098 | } |
1101 | 1099 | ||
1102 | static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, | 1100 | static int macvtap_recvmsg(struct kiocb *iocb, struct socket *sock, |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 405dfdf4f8c8..4b743c612624 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -1012,28 +1012,29 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile, | |||
1012 | 1012 | ||
1013 | /* Get packet from user space buffer */ | 1013 | /* Get packet from user space buffer */ |
1014 | static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | 1014 | static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, |
1015 | void *msg_control, const struct iovec *iv, | 1015 | void *msg_control, struct iov_iter *from, |
1016 | size_t total_len, size_t count, int noblock) | 1016 | int noblock) |
1017 | { | 1017 | { |
1018 | struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; | 1018 | struct tun_pi pi = { 0, cpu_to_be16(ETH_P_IP) }; |
1019 | struct sk_buff *skb; | 1019 | struct sk_buff *skb; |
1020 | size_t total_len = iov_iter_count(from); | ||
1020 | size_t len = total_len, align = NET_SKB_PAD, linear; | 1021 | size_t len = total_len, align = NET_SKB_PAD, linear; |
1021 | struct virtio_net_hdr gso = { 0 }; | 1022 | struct virtio_net_hdr gso = { 0 }; |
1022 | int good_linear; | 1023 | int good_linear; |
1023 | int offset = 0; | ||
1024 | int copylen; | 1024 | int copylen; |
1025 | bool zerocopy = false; | 1025 | bool zerocopy = false; |
1026 | int err; | 1026 | int err; |
1027 | u32 rxhash; | 1027 | u32 rxhash; |
1028 | ssize_t n; | ||
1028 | 1029 | ||
1029 | if (!(tun->flags & TUN_NO_PI)) { | 1030 | if (!(tun->flags & TUN_NO_PI)) { |
1030 | if (len < sizeof(pi)) | 1031 | if (len < sizeof(pi)) |
1031 | return -EINVAL; | 1032 | return -EINVAL; |
1032 | len -= sizeof(pi); | 1033 | len -= sizeof(pi); |
1033 | 1034 | ||
1034 | if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) | 1035 | n = copy_from_iter(&pi, sizeof(pi), from); |
1036 | if (n != sizeof(pi)) | ||
1035 | return -EFAULT; | 1037 | return -EFAULT; |
1036 | offset += sizeof(pi); | ||
1037 | } | 1038 | } |
1038 | 1039 | ||
1039 | if (tun->flags & TUN_VNET_HDR) { | 1040 | if (tun->flags & TUN_VNET_HDR) { |
@@ -1041,7 +1042,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1041 | return -EINVAL; | 1042 | return -EINVAL; |
1042 | len -= tun->vnet_hdr_sz; | 1043 | len -= tun->vnet_hdr_sz; |
1043 | 1044 | ||
1044 | if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) | 1045 | n = copy_from_iter(&gso, sizeof(gso), from); |
1046 | if (n != sizeof(gso)) | ||
1045 | return -EFAULT; | 1047 | return -EFAULT; |
1046 | 1048 | ||
1047 | if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && | 1049 | if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && |
@@ -1050,7 +1052,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1050 | 1052 | ||
1051 | if (gso.hdr_len > len) | 1053 | if (gso.hdr_len > len) |
1052 | return -EINVAL; | 1054 | return -EINVAL; |
1053 | offset += tun->vnet_hdr_sz; | 1055 | iov_iter_advance(from, tun->vnet_hdr_sz); |
1054 | } | 1056 | } |
1055 | 1057 | ||
1056 | if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { | 1058 | if ((tun->flags & TUN_TYPE_MASK) == TUN_TAP_DEV) { |
@@ -1063,6 +1065,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1063 | good_linear = SKB_MAX_HEAD(align); | 1065 | good_linear = SKB_MAX_HEAD(align); |
1064 | 1066 | ||
1065 | if (msg_control) { | 1067 | if (msg_control) { |
1068 | struct iov_iter i = *from; | ||
1069 | |||
1066 | /* There are 256 bytes to be copied in skb, so there is | 1070 | /* There are 256 bytes to be copied in skb, so there is |
1067 | * enough room for skb expand head in case it is used. | 1071 | * enough room for skb expand head in case it is used. |
1068 | * The rest of the buffer is mapped from userspace. | 1072 | * The rest of the buffer is mapped from userspace. |
@@ -1071,7 +1075,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1071 | if (copylen > good_linear) | 1075 | if (copylen > good_linear) |
1072 | copylen = good_linear; | 1076 | copylen = good_linear; |
1073 | linear = copylen; | 1077 | linear = copylen; |
1074 | if (iov_pages(iv, offset + copylen, count) <= MAX_SKB_FRAGS) | 1078 | iov_iter_advance(&i, copylen); |
1079 | if (iov_iter_npages(&i, INT_MAX) <= MAX_SKB_FRAGS) | ||
1075 | zerocopy = true; | 1080 | zerocopy = true; |
1076 | } | 1081 | } |
1077 | 1082 | ||
@@ -1091,9 +1096,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1091 | } | 1096 | } |
1092 | 1097 | ||
1093 | if (zerocopy) | 1098 | if (zerocopy) |
1094 | err = zerocopy_sg_from_iovec(skb, iv, offset, count); | 1099 | err = zerocopy_sg_from_iter(skb, from); |
1095 | else { | 1100 | else { |
1096 | err = skb_copy_datagram_from_iovec(skb, 0, iv, offset, len); | 1101 | err = skb_copy_datagram_from_iter(skb, 0, from, len); |
1097 | if (!err && msg_control) { | 1102 | if (!err && msg_control) { |
1098 | struct ubuf_info *uarg = msg_control; | 1103 | struct ubuf_info *uarg = msg_control; |
1099 | uarg->callback(uarg, false); | 1104 | uarg->callback(uarg, false); |
@@ -1207,8 +1212,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1207 | return total_len; | 1212 | return total_len; |
1208 | } | 1213 | } |
1209 | 1214 | ||
1210 | static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, | 1215 | static ssize_t tun_chr_write_iter(struct kiocb *iocb, struct iov_iter *from) |
1211 | unsigned long count, loff_t pos) | ||
1212 | { | 1216 | { |
1213 | struct file *file = iocb->ki_filp; | 1217 | struct file *file = iocb->ki_filp; |
1214 | struct tun_struct *tun = tun_get(file); | 1218 | struct tun_struct *tun = tun_get(file); |
@@ -1218,10 +1222,7 @@ static ssize_t tun_chr_aio_write(struct kiocb *iocb, const struct iovec *iv, | |||
1218 | if (!tun) | 1222 | if (!tun) |
1219 | return -EBADFD; | 1223 | return -EBADFD; |
1220 | 1224 | ||
1221 | tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count); | 1225 | result = tun_get_user(tun, tfile, NULL, from, file->f_flags & O_NONBLOCK); |
1222 | |||
1223 | result = tun_get_user(tun, tfile, NULL, iv, iov_length(iv, count), | ||
1224 | count, file->f_flags & O_NONBLOCK); | ||
1225 | 1226 | ||
1226 | tun_put(tun); | 1227 | tun_put(tun); |
1227 | return result; | 1228 | return result; |
@@ -1445,11 +1446,14 @@ static int tun_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1445 | int ret; | 1446 | int ret; |
1446 | struct tun_file *tfile = container_of(sock, struct tun_file, socket); | 1447 | struct tun_file *tfile = container_of(sock, struct tun_file, socket); |
1447 | struct tun_struct *tun = __tun_get(tfile); | 1448 | struct tun_struct *tun = __tun_get(tfile); |
1449 | struct iov_iter from; | ||
1448 | 1450 | ||
1449 | if (!tun) | 1451 | if (!tun) |
1450 | return -EBADFD; | 1452 | return -EBADFD; |
1451 | ret = tun_get_user(tun, tfile, m->msg_control, m->msg_iov, total_len, | 1453 | |
1452 | m->msg_iovlen, m->msg_flags & MSG_DONTWAIT); | 1454 | iov_iter_init(&from, WRITE, m->msg_iov, m->msg_iovlen, total_len); |
1455 | ret = tun_get_user(tun, tfile, m->msg_control, &from, | ||
1456 | m->msg_flags & MSG_DONTWAIT); | ||
1453 | tun_put(tun); | 1457 | tun_put(tun); |
1454 | return ret; | 1458 | return ret; |
1455 | } | 1459 | } |
@@ -2233,9 +2237,9 @@ static const struct file_operations tun_fops = { | |||
2233 | .owner = THIS_MODULE, | 2237 | .owner = THIS_MODULE, |
2234 | .llseek = no_llseek, | 2238 | .llseek = no_llseek, |
2235 | .read = new_sync_read, | 2239 | .read = new_sync_read, |
2240 | .write = new_sync_write, | ||
2236 | .read_iter = tun_chr_read_iter, | 2241 | .read_iter = tun_chr_read_iter, |
2237 | .write = do_sync_write, | 2242 | .write_iter = tun_chr_write_iter, |
2238 | .aio_write = tun_chr_aio_write, | ||
2239 | .poll = tun_chr_poll, | 2243 | .poll = tun_chr_poll, |
2240 | .unlocked_ioctl = tun_chr_ioctl, | 2244 | .unlocked_ioctl = tun_chr_ioctl, |
2241 | #ifdef CONFIG_COMPAT | 2245 | #ifdef CONFIG_COMPAT |