diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-11-01 22:09:04 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-12-05 14:33:36 -0500 |
commit | cbbd26b8b1a6af9c02e2b6523e12bd50cc765059 (patch) | |
tree | 6d1b258c99e83f320cf3611bdc927121df7e9b03 | |
parent | e5517c2a5a49ed5e99047008629f1cd60246ea0e (diff) |
[iov_iter] new primitives - copy_from_iter_full() and friends
copy_from_iter_full(), copy_from_iter_full_nocache() and
csum_and_copy_from_iter_full() - counterparts of copy_from_iter()
et.al., advancing iterator only in case of successful full copy
and returning whether it had been successful or not.
Convert some obvious users. *NOTE* - do not blindly assume that
something is a good candidate for those unless you are sure that
not advancing iov_iter in failure case is the right thing in
this case. Anything that does short read/short write kind of
stuff (or is in a loop, etc.) is unlikely to be a good one.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | drivers/bluetooth/hci_vhci.c | 2 | ||||
-rw-r--r-- | drivers/net/macvtap.c | 4 | ||||
-rw-r--r-- | drivers/net/tun.c | 7 | ||||
-rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/inode.c | 2 | ||||
-rw-r--r-- | drivers/vhost/scsi.c | 3 | ||||
-rw-r--r-- | drivers/vhost/vhost.c | 3 | ||||
-rw-r--r-- | fs/ncpfs/file.c | 2 | ||||
-rw-r--r-- | fs/orangefs/devorangefs-req.c | 13 | ||||
-rw-r--r-- | include/linux/uio.h | 3 | ||||
-rw-r--r-- | kernel/printk/printk.c | 2 | ||||
-rw-r--r-- | lib/iov_iter.c | 98 | ||||
-rw-r--r-- | net/atm/common.c | 2 | ||||
-rw-r--r-- | net/bluetooth/l2cap_core.c | 6 | ||||
-rw-r--r-- | net/packet/af_packet.c | 5 | ||||
-rw-r--r-- | net/tipc/msg.c | 4 | ||||
-rw-r--r-- | security/keys/keyctl.c | 2 |
17 files changed, 121 insertions, 39 deletions
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index c4a75a18dcae..233e850fdac7 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
@@ -181,7 +181,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, | |||
181 | if (!skb) | 181 | if (!skb) |
182 | return -ENOMEM; | 182 | return -ENOMEM; |
183 | 183 | ||
184 | if (copy_from_iter(skb_put(skb, len), len, from) != len) { | 184 | if (!copy_from_iter_full(skb_put(skb, len), len, from)) { |
185 | kfree_skb(skb); | 185 | kfree_skb(skb); |
186 | return -EFAULT; | 186 | return -EFAULT; |
187 | } | 187 | } |
diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 070e3290aa6e..19d81ca3fb49 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c | |||
@@ -673,7 +673,6 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
673 | int depth; | 673 | int depth; |
674 | bool zerocopy = false; | 674 | bool zerocopy = false; |
675 | size_t linear; | 675 | size_t linear; |
676 | ssize_t n; | ||
677 | 676 | ||
678 | if (q->flags & IFF_VNET_HDR) { | 677 | if (q->flags & IFF_VNET_HDR) { |
679 | vnet_hdr_len = q->vnet_hdr_sz; | 678 | vnet_hdr_len = q->vnet_hdr_sz; |
@@ -684,8 +683,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, | |||
684 | len -= vnet_hdr_len; | 683 | len -= vnet_hdr_len; |
685 | 684 | ||
686 | err = -EFAULT; | 685 | err = -EFAULT; |
687 | n = copy_from_iter(&vnet_hdr, sizeof(vnet_hdr), from); | 686 | if (!copy_from_iter_full(&vnet_hdr, sizeof(vnet_hdr), from)) |
688 | if (n != sizeof(vnet_hdr)) | ||
689 | goto err; | 687 | goto err; |
690 | iov_iter_advance(from, vnet_hdr_len - sizeof(vnet_hdr)); | 688 | iov_iter_advance(from, vnet_hdr_len - sizeof(vnet_hdr)); |
691 | if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && | 689 | if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 8093e39ae263..4fa2d756548a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -1171,7 +1171,6 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1171 | bool zerocopy = false; | 1171 | bool zerocopy = false; |
1172 | int err; | 1172 | int err; |
1173 | u32 rxhash; | 1173 | u32 rxhash; |
1174 | ssize_t n; | ||
1175 | 1174 | ||
1176 | if (!(tun->dev->flags & IFF_UP)) | 1175 | if (!(tun->dev->flags & IFF_UP)) |
1177 | return -EIO; | 1176 | return -EIO; |
@@ -1181,8 +1180,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1181 | return -EINVAL; | 1180 | return -EINVAL; |
1182 | len -= sizeof(pi); | 1181 | len -= sizeof(pi); |
1183 | 1182 | ||
1184 | n = copy_from_iter(&pi, sizeof(pi), from); | 1183 | if (!copy_from_iter_full(&pi, sizeof(pi), from)) |
1185 | if (n != sizeof(pi)) | ||
1186 | return -EFAULT; | 1184 | return -EFAULT; |
1187 | } | 1185 | } |
1188 | 1186 | ||
@@ -1191,8 +1189,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1191 | return -EINVAL; | 1189 | return -EINVAL; |
1192 | len -= tun->vnet_hdr_sz; | 1190 | len -= tun->vnet_hdr_sz; |
1193 | 1191 | ||
1194 | n = copy_from_iter(&gso, sizeof(gso), from); | 1192 | if (!copy_from_iter_full(&gso, sizeof(gso), from)) |
1195 | if (n != sizeof(gso)) | ||
1196 | return -EFAULT; | 1193 | return -EFAULT; |
1197 | 1194 | ||
1198 | if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && | 1195 | if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && |
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 17989b72cdae..0bfd1e25b431 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
@@ -949,7 +949,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) | |||
949 | goto error_mutex; | 949 | goto error_mutex; |
950 | } | 950 | } |
951 | if (!io_data->read && | 951 | if (!io_data->read && |
952 | copy_from_iter(data, data_len, &io_data->data) != data_len) { | 952 | !copy_from_iter_full(data, data_len, &io_data->data)) { |
953 | ret = -EFAULT; | 953 | ret = -EFAULT; |
954 | goto error_mutex; | 954 | goto error_mutex; |
955 | } | 955 | } |
diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index bd82dd12deff..10b2576f8b6a 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c | |||
@@ -667,7 +667,7 @@ ep_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
667 | return -ENOMEM; | 667 | return -ENOMEM; |
668 | } | 668 | } |
669 | 669 | ||
670 | if (unlikely(copy_from_iter(buf, len, from) != len)) { | 670 | if (unlikely(!copy_from_iter_full(buf, len, from))) { |
671 | value = -EFAULT; | 671 | value = -EFAULT; |
672 | goto out; | 672 | goto out; |
673 | } | 673 | } |
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 6e29d053843d..b296985fda0d 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c | |||
@@ -922,8 +922,7 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq) | |||
922 | */ | 922 | */ |
923 | iov_iter_init(&out_iter, WRITE, vq->iov, out, out_size); | 923 | iov_iter_init(&out_iter, WRITE, vq->iov, out, out_size); |
924 | 924 | ||
925 | ret = copy_from_iter(req, req_size, &out_iter); | 925 | if (unlikely(!copy_from_iter_full(req, req_size, &out_iter))) { |
926 | if (unlikely(ret != req_size)) { | ||
927 | vq_err(vq, "Faulted on copy_from_iter\n"); | 926 | vq_err(vq, "Faulted on copy_from_iter\n"); |
928 | vhost_scsi_send_bad_target(vs, vq, head, out); | 927 | vhost_scsi_send_bad_target(vs, vq, head, out); |
929 | continue; | 928 | continue; |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index c6f2d89c0e97..06e8b81b6253 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -1862,8 +1862,7 @@ static int get_indirect(struct vhost_virtqueue *vq, | |||
1862 | i, count); | 1862 | i, count); |
1863 | return -EINVAL; | 1863 | return -EINVAL; |
1864 | } | 1864 | } |
1865 | if (unlikely(copy_from_iter(&desc, sizeof(desc), &from) != | 1865 | if (unlikely(!copy_from_iter_full(&desc, sizeof(desc), &from))) { |
1866 | sizeof(desc))) { | ||
1867 | vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n", | 1866 | vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n", |
1868 | i, (size_t)vhost64_to_cpu(vq, indirect->addr) + i * sizeof desc); | 1867 | i, (size_t)vhost64_to_cpu(vq, indirect->addr) + i * sizeof desc); |
1869 | return -EINVAL; | 1868 | return -EINVAL; |
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index dd38ca1f2ecb..83ca77231707 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c | |||
@@ -203,7 +203,7 @@ ncp_file_write_iter(struct kiocb *iocb, struct iov_iter *from) | |||
203 | bufsize - (pos % bufsize), | 203 | bufsize - (pos % bufsize), |
204 | iov_iter_count(from)); | 204 | iov_iter_count(from)); |
205 | 205 | ||
206 | if (copy_from_iter(bouncebuffer, to_write, from) != to_write) { | 206 | if (!copy_from_iter_full(bouncebuffer, to_write, from)) { |
207 | errno = -EFAULT; | 207 | errno = -EFAULT; |
208 | break; | 208 | break; |
209 | } | 209 | } |
diff --git a/fs/orangefs/devorangefs-req.c b/fs/orangefs/devorangefs-req.c index 516ffb4dc9a0..b0ced669427e 100644 --- a/fs/orangefs/devorangefs-req.c +++ b/fs/orangefs/devorangefs-req.c | |||
@@ -355,7 +355,6 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, | |||
355 | __u64 tag; | 355 | __u64 tag; |
356 | } head; | 356 | } head; |
357 | int total = ret = iov_iter_count(iter); | 357 | int total = ret = iov_iter_count(iter); |
358 | int n; | ||
359 | int downcall_size = sizeof(struct orangefs_downcall_s); | 358 | int downcall_size = sizeof(struct orangefs_downcall_s); |
360 | int head_size = sizeof(head); | 359 | int head_size = sizeof(head); |
361 | 360 | ||
@@ -372,8 +371,7 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, | |||
372 | return -EFAULT; | 371 | return -EFAULT; |
373 | } | 372 | } |
374 | 373 | ||
375 | n = copy_from_iter(&head, head_size, iter); | 374 | if (!copy_from_iter_full(&head, head_size, iter)) { |
376 | if (n < head_size) { | ||
377 | gossip_err("%s: failed to copy head.\n", __func__); | 375 | gossip_err("%s: failed to copy head.\n", __func__); |
378 | return -EFAULT; | 376 | return -EFAULT; |
379 | } | 377 | } |
@@ -407,8 +405,7 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, | |||
407 | return ret; | 405 | return ret; |
408 | } | 406 | } |
409 | 407 | ||
410 | n = copy_from_iter(&op->downcall, downcall_size, iter); | 408 | if (!copy_from_iter_full(&op->downcall, downcall_size, iter)) { |
411 | if (n != downcall_size) { | ||
412 | gossip_err("%s: failed to copy downcall.\n", __func__); | 409 | gossip_err("%s: failed to copy downcall.\n", __func__); |
413 | goto Efault; | 410 | goto Efault; |
414 | } | 411 | } |
@@ -462,10 +459,8 @@ static ssize_t orangefs_devreq_write_iter(struct kiocb *iocb, | |||
462 | goto Enomem; | 459 | goto Enomem; |
463 | } | 460 | } |
464 | memset(op->downcall.trailer_buf, 0, op->downcall.trailer_size); | 461 | memset(op->downcall.trailer_buf, 0, op->downcall.trailer_size); |
465 | n = copy_from_iter(op->downcall.trailer_buf, | 462 | if (!copy_from_iter_full(op->downcall.trailer_buf, |
466 | op->downcall.trailer_size, | 463 | op->downcall.trailer_size, iter)) { |
467 | iter); | ||
468 | if (n != op->downcall.trailer_size) { | ||
469 | gossip_err("%s: failed to copy trailer.\n", __func__); | 464 | gossip_err("%s: failed to copy trailer.\n", __func__); |
470 | vfree(op->downcall.trailer_buf); | 465 | vfree(op->downcall.trailer_buf); |
471 | goto Efault; | 466 | goto Efault; |
diff --git a/include/linux/uio.h b/include/linux/uio.h index 6e22b544d039..e57c0ccd61c6 100644 --- a/include/linux/uio.h +++ b/include/linux/uio.h | |||
@@ -89,7 +89,9 @@ size_t copy_page_from_iter(struct page *page, size_t offset, size_t bytes, | |||
89 | struct iov_iter *i); | 89 | struct iov_iter *i); |
90 | size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i); | 90 | size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i); |
91 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); | 91 | size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i); |
92 | bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i); | ||
92 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i); | 93 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i); |
94 | bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i); | ||
93 | size_t iov_iter_zero(size_t bytes, struct iov_iter *); | 95 | size_t iov_iter_zero(size_t bytes, struct iov_iter *); |
94 | unsigned long iov_iter_alignment(const struct iov_iter *i); | 96 | unsigned long iov_iter_alignment(const struct iov_iter *i); |
95 | unsigned long iov_iter_gap_alignment(const struct iov_iter *i); | 97 | unsigned long iov_iter_gap_alignment(const struct iov_iter *i); |
@@ -155,6 +157,7 @@ static inline void iov_iter_reexpand(struct iov_iter *i, size_t count) | |||
155 | } | 157 | } |
156 | size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); | 158 | size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); |
157 | size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); | 159 | size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); |
160 | bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); | ||
158 | 161 | ||
159 | int import_iovec(int type, const struct iovec __user * uvector, | 162 | int import_iovec(int type, const struct iovec __user * uvector, |
160 | unsigned nr_segs, unsigned fast_segs, | 163 | unsigned nr_segs, unsigned fast_segs, |
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index f7a55e9ff2f7..f6bda15396df 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c | |||
@@ -748,7 +748,7 @@ static ssize_t devkmsg_write(struct kiocb *iocb, struct iov_iter *from) | |||
748 | return -ENOMEM; | 748 | return -ENOMEM; |
749 | 749 | ||
750 | buf[len] = '\0'; | 750 | buf[len] = '\0'; |
751 | if (copy_from_iter(buf, len, from) != len) { | 751 | if (!copy_from_iter_full(buf, len, from)) { |
752 | kfree(buf); | 752 | kfree(buf); |
753 | return -EFAULT; | 753 | return -EFAULT; |
754 | } | 754 | } |
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index f2bd21b93dfc..83c00b7f59b5 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c | |||
@@ -568,6 +568,31 @@ size_t copy_from_iter(void *addr, size_t bytes, struct iov_iter *i) | |||
568 | } | 568 | } |
569 | EXPORT_SYMBOL(copy_from_iter); | 569 | EXPORT_SYMBOL(copy_from_iter); |
570 | 570 | ||
571 | bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i) | ||
572 | { | ||
573 | char *to = addr; | ||
574 | if (unlikely(i->type & ITER_PIPE)) { | ||
575 | WARN_ON(1); | ||
576 | return false; | ||
577 | } | ||
578 | if (unlikely(i->count < bytes)) \ | ||
579 | return false; | ||
580 | |||
581 | iterate_all_kinds(i, bytes, v, ({ | ||
582 | if (__copy_from_user((to += v.iov_len) - v.iov_len, | ||
583 | v.iov_base, v.iov_len)) | ||
584 | return false; | ||
585 | 0;}), | ||
586 | memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, | ||
587 | v.bv_offset, v.bv_len), | ||
588 | memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) | ||
589 | ) | ||
590 | |||
591 | iov_iter_advance(i, bytes); | ||
592 | return true; | ||
593 | } | ||
594 | EXPORT_SYMBOL(copy_from_iter_full); | ||
595 | |||
571 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) | 596 | size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) |
572 | { | 597 | { |
573 | char *to = addr; | 598 | char *to = addr; |
@@ -587,6 +612,30 @@ size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) | |||
587 | } | 612 | } |
588 | EXPORT_SYMBOL(copy_from_iter_nocache); | 613 | EXPORT_SYMBOL(copy_from_iter_nocache); |
589 | 614 | ||
615 | bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i) | ||
616 | { | ||
617 | char *to = addr; | ||
618 | if (unlikely(i->type & ITER_PIPE)) { | ||
619 | WARN_ON(1); | ||
620 | return false; | ||
621 | } | ||
622 | if (unlikely(i->count < bytes)) \ | ||
623 | return false; | ||
624 | iterate_all_kinds(i, bytes, v, ({ | ||
625 | if (__copy_from_user_nocache((to += v.iov_len) - v.iov_len, | ||
626 | v.iov_base, v.iov_len)) | ||
627 | return false; | ||
628 | 0;}), | ||
629 | memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, | ||
630 | v.bv_offset, v.bv_len), | ||
631 | memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) | ||
632 | ) | ||
633 | |||
634 | iov_iter_advance(i, bytes); | ||
635 | return true; | ||
636 | } | ||
637 | EXPORT_SYMBOL(copy_from_iter_full_nocache); | ||
638 | |||
590 | size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, | 639 | size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, |
591 | struct iov_iter *i) | 640 | struct iov_iter *i) |
592 | { | 641 | { |
@@ -1008,7 +1057,7 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, | |||
1008 | } | 1057 | } |
1009 | iterate_and_advance(i, bytes, v, ({ | 1058 | iterate_and_advance(i, bytes, v, ({ |
1010 | int err = 0; | 1059 | int err = 0; |
1011 | next = csum_and_copy_from_user(v.iov_base, | 1060 | next = csum_and_copy_from_user(v.iov_base, |
1012 | (to += v.iov_len) - v.iov_len, | 1061 | (to += v.iov_len) - v.iov_len, |
1013 | v.iov_len, 0, &err); | 1062 | v.iov_len, 0, &err); |
1014 | if (!err) { | 1063 | if (!err) { |
@@ -1037,6 +1086,51 @@ size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, | |||
1037 | } | 1086 | } |
1038 | EXPORT_SYMBOL(csum_and_copy_from_iter); | 1087 | EXPORT_SYMBOL(csum_and_copy_from_iter); |
1039 | 1088 | ||
1089 | bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, | ||
1090 | struct iov_iter *i) | ||
1091 | { | ||
1092 | char *to = addr; | ||
1093 | __wsum sum, next; | ||
1094 | size_t off = 0; | ||
1095 | sum = *csum; | ||
1096 | if (unlikely(i->type & ITER_PIPE)) { | ||
1097 | WARN_ON(1); | ||
1098 | return false; | ||
1099 | } | ||
1100 | if (unlikely(i->count < bytes)) | ||
1101 | return false; | ||
1102 | iterate_all_kinds(i, bytes, v, ({ | ||
1103 | int err = 0; | ||
1104 | next = csum_and_copy_from_user(v.iov_base, | ||
1105 | (to += v.iov_len) - v.iov_len, | ||
1106 | v.iov_len, 0, &err); | ||
1107 | if (err) | ||
1108 | return false; | ||
1109 | sum = csum_block_add(sum, next, off); | ||
1110 | off += v.iov_len; | ||
1111 | 0; | ||
1112 | }), ({ | ||
1113 | char *p = kmap_atomic(v.bv_page); | ||
1114 | next = csum_partial_copy_nocheck(p + v.bv_offset, | ||
1115 | (to += v.bv_len) - v.bv_len, | ||
1116 | v.bv_len, 0); | ||
1117 | kunmap_atomic(p); | ||
1118 | sum = csum_block_add(sum, next, off); | ||
1119 | off += v.bv_len; | ||
1120 | }),({ | ||
1121 | next = csum_partial_copy_nocheck(v.iov_base, | ||
1122 | (to += v.iov_len) - v.iov_len, | ||
1123 | v.iov_len, 0); | ||
1124 | sum = csum_block_add(sum, next, off); | ||
1125 | off += v.iov_len; | ||
1126 | }) | ||
1127 | ) | ||
1128 | *csum = sum; | ||
1129 | iov_iter_advance(i, bytes); | ||
1130 | return true; | ||
1131 | } | ||
1132 | EXPORT_SYMBOL(csum_and_copy_from_iter_full); | ||
1133 | |||
1040 | size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, | 1134 | size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, |
1041 | struct iov_iter *i) | 1135 | struct iov_iter *i) |
1042 | { | 1136 | { |
@@ -1051,7 +1145,7 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, | |||
1051 | iterate_and_advance(i, bytes, v, ({ | 1145 | iterate_and_advance(i, bytes, v, ({ |
1052 | int err = 0; | 1146 | int err = 0; |
1053 | next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len, | 1147 | next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len, |
1054 | v.iov_base, | 1148 | v.iov_base, |
1055 | v.iov_len, 0, &err); | 1149 | v.iov_len, 0, &err); |
1056 | if (!err) { | 1150 | if (!err) { |
1057 | sum = csum_block_add(sum, next, off); | 1151 | sum = csum_block_add(sum, next, off); |
diff --git a/net/atm/common.c b/net/atm/common.c index 6dc12305799e..a3ca922d307b 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -630,7 +630,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size) | |||
630 | goto out; | 630 | goto out; |
631 | skb->dev = NULL; /* for paths shared with net_device interfaces */ | 631 | skb->dev = NULL; /* for paths shared with net_device interfaces */ |
632 | ATM_SKB(skb)->atm_options = vcc->atm_options; | 632 | ATM_SKB(skb)->atm_options = vcc->atm_options; |
633 | if (copy_from_iter(skb_put(skb, size), size, &m->msg_iter) != size) { | 633 | if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) { |
634 | kfree_skb(skb); | 634 | kfree_skb(skb); |
635 | error = -EFAULT; | 635 | error = -EFAULT; |
636 | goto out; | 636 | goto out; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 577f1c01454a..ce0b5dd01953 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -2127,7 +2127,7 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | |||
2127 | struct sk_buff **frag; | 2127 | struct sk_buff **frag; |
2128 | int sent = 0; | 2128 | int sent = 0; |
2129 | 2129 | ||
2130 | if (copy_from_iter(skb_put(skb, count), count, &msg->msg_iter) != count) | 2130 | if (!copy_from_iter_full(skb_put(skb, count), count, &msg->msg_iter)) |
2131 | return -EFAULT; | 2131 | return -EFAULT; |
2132 | 2132 | ||
2133 | sent += count; | 2133 | sent += count; |
@@ -2147,8 +2147,8 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | |||
2147 | 2147 | ||
2148 | *frag = tmp; | 2148 | *frag = tmp; |
2149 | 2149 | ||
2150 | if (copy_from_iter(skb_put(*frag, count), count, | 2150 | if (!copy_from_iter_full(skb_put(*frag, count), count, |
2151 | &msg->msg_iter) != count) | 2151 | &msg->msg_iter)) |
2152 | return -EFAULT; | 2152 | return -EFAULT; |
2153 | 2153 | ||
2154 | sent += count; | 2154 | sent += count; |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index d2238b204691..588ec202d5ba 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -2432,14 +2432,11 @@ static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len) | |||
2432 | static int packet_snd_vnet_parse(struct msghdr *msg, size_t *len, | 2432 | static int packet_snd_vnet_parse(struct msghdr *msg, size_t *len, |
2433 | struct virtio_net_hdr *vnet_hdr) | 2433 | struct virtio_net_hdr *vnet_hdr) |
2434 | { | 2434 | { |
2435 | int n; | ||
2436 | |||
2437 | if (*len < sizeof(*vnet_hdr)) | 2435 | if (*len < sizeof(*vnet_hdr)) |
2438 | return -EINVAL; | 2436 | return -EINVAL; |
2439 | *len -= sizeof(*vnet_hdr); | 2437 | *len -= sizeof(*vnet_hdr); |
2440 | 2438 | ||
2441 | n = copy_from_iter(vnet_hdr, sizeof(*vnet_hdr), &msg->msg_iter); | 2439 | if (!copy_from_iter_full(vnet_hdr, sizeof(*vnet_hdr), &msg->msg_iter)) |
2442 | if (n != sizeof(*vnet_hdr)) | ||
2443 | return -EFAULT; | 2440 | return -EFAULT; |
2444 | 2441 | ||
2445 | return __packet_snd_vnet_parse(vnet_hdr, *len); | 2442 | return __packet_snd_vnet_parse(vnet_hdr, *len); |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 17201aa8423d..a22be502f1bd 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -268,7 +268,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, | |||
268 | __skb_queue_tail(list, skb); | 268 | __skb_queue_tail(list, skb); |
269 | skb_copy_to_linear_data(skb, mhdr, mhsz); | 269 | skb_copy_to_linear_data(skb, mhdr, mhsz); |
270 | pktpos = skb->data + mhsz; | 270 | pktpos = skb->data + mhsz; |
271 | if (copy_from_iter(pktpos, dsz, &m->msg_iter) == dsz) | 271 | if (copy_from_iter_full(pktpos, dsz, &m->msg_iter)) |
272 | return dsz; | 272 | return dsz; |
273 | rc = -EFAULT; | 273 | rc = -EFAULT; |
274 | goto error; | 274 | goto error; |
@@ -299,7 +299,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, | |||
299 | if (drem < pktrem) | 299 | if (drem < pktrem) |
300 | pktrem = drem; | 300 | pktrem = drem; |
301 | 301 | ||
302 | if (copy_from_iter(pktpos, pktrem, &m->msg_iter) != pktrem) { | 302 | if (!copy_from_iter_full(pktpos, pktrem, &m->msg_iter)) { |
303 | rc = -EFAULT; | 303 | rc = -EFAULT; |
304 | goto error; | 304 | goto error; |
305 | } | 305 | } |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index d580ad06b792..f89f1900e58d 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1074,7 +1074,7 @@ long keyctl_instantiate_key_common(key_serial_t id, | |||
1074 | } | 1074 | } |
1075 | 1075 | ||
1076 | ret = -EFAULT; | 1076 | ret = -EFAULT; |
1077 | if (copy_from_iter(payload, plen, from) != plen) | 1077 | if (!copy_from_iter_full(payload, plen, from)) |
1078 | goto error2; | 1078 | goto error2; |
1079 | } | 1079 | } |
1080 | 1080 | ||