Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

Al Viro cbbd26b8 e5517c2a

+121 -39
+1 -1
drivers/bluetooth/hci_vhci.c
··· 181 181 if (!skb) 182 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 185 kfree_skb(skb); 186 186 return -EFAULT; 187 187 }
+1 -3
drivers/net/macvtap.c
··· 673 673 int depth; 674 674 bool zerocopy = false; 675 675 size_t linear; 676 - ssize_t n; 677 676 678 677 if (q->flags & IFF_VNET_HDR) { 679 678 vnet_hdr_len = q->vnet_hdr_sz; ··· 683 684 len -= vnet_hdr_len; 684 685 685 686 err = -EFAULT; 686 - n = copy_from_iter(&vnet_hdr, sizeof(vnet_hdr), from); 687 - if (n != sizeof(vnet_hdr)) 687 + if (!copy_from_iter_full(&vnet_hdr, sizeof(vnet_hdr), from)) 688 688 goto err; 689 689 iov_iter_advance(from, vnet_hdr_len - sizeof(vnet_hdr)); 690 690 if ((vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
+2 -5
drivers/net/tun.c
··· 1171 1171 bool zerocopy = false; 1172 1172 int err; 1173 1173 u32 rxhash; 1174 - ssize_t n; 1175 1174 1176 1175 if (!(tun->dev->flags & IFF_UP)) 1177 1176 return -EIO; ··· 1180 1181 return -EINVAL; 1181 1182 len -= sizeof(pi); 1182 1183 1183 - n = copy_from_iter(&pi, sizeof(pi), from); 1184 - if (n != sizeof(pi)) 1184 + if (!copy_from_iter_full(&pi, sizeof(pi), from)) 1185 1185 return -EFAULT; 1186 1186 } 1187 1187 ··· 1189 1191 return -EINVAL; 1190 1192 len -= tun->vnet_hdr_sz; 1191 1193 1192 - n = copy_from_iter(&gso, sizeof(gso), from); 1193 - if (n != sizeof(gso)) 1194 + if (!copy_from_iter_full(&gso, sizeof(gso), from)) 1194 1195 return -EFAULT; 1195 1196 1196 1197 if ((gso.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
+1 -1
drivers/usb/gadget/function/f_fs.c
··· 949 949 goto error_mutex; 950 950 } 951 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 953 ret = -EFAULT; 954 954 goto error_mutex; 955 955 }
+1 -1
drivers/usb/gadget/legacy/inode.c
··· 667 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 671 value = -EFAULT; 672 672 goto out; 673 673 }
+1 -2
drivers/vhost/scsi.c
··· 922 922 */ 923 923 iov_iter_init(&out_iter, WRITE, vq->iov, out, out_size); 924 924 925 - ret = copy_from_iter(req, req_size, &out_iter); 926 - if (unlikely(ret != req_size)) { 925 + if (unlikely(!copy_from_iter_full(req, req_size, &out_iter))) { 927 926 vq_err(vq, "Faulted on copy_from_iter\n"); 928 927 vhost_scsi_send_bad_target(vs, vq, head, out); 929 928 continue;
+1 -2
drivers/vhost/vhost.c
··· 1862 1862 i, count); 1863 1863 return -EINVAL; 1864 1864 } 1865 - if (unlikely(copy_from_iter(&desc, sizeof(desc), &from) != 1866 - sizeof(desc))) { 1865 + if (unlikely(!copy_from_iter_full(&desc, sizeof(desc), &from))) { 1867 1866 vq_err(vq, "Failed indirect descriptor: idx %d, %zx\n", 1868 1867 i, (size_t)vhost64_to_cpu(vq, indirect->addr) + i * sizeof desc); 1869 1868 return -EINVAL;
+1 -1
fs/ncpfs/file.c
··· 203 203 bufsize - (pos % bufsize), 204 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 207 errno = -EFAULT; 208 208 break; 209 209 }
+4 -9
fs/orangefs/devorangefs-req.c
··· 355 355 __u64 tag; 356 356 } head; 357 357 int total = ret = iov_iter_count(iter); 358 - int n; 359 358 int downcall_size = sizeof(struct orangefs_downcall_s); 360 359 int head_size = sizeof(head); 361 360 ··· 371 372 return -EFAULT; 372 373 } 373 374 374 - n = copy_from_iter(&head, head_size, iter); 375 - if (n < head_size) { 375 + if (!copy_from_iter_full(&head, head_size, iter)) { 376 376 gossip_err("%s: failed to copy head.\n", __func__); 377 377 return -EFAULT; 378 378 } ··· 405 407 return ret; 406 408 } 407 409 408 - n = copy_from_iter(&op->downcall, downcall_size, iter); 409 - if (n != downcall_size) { 410 + if (!copy_from_iter_full(&op->downcall, downcall_size, iter)) { 410 411 gossip_err("%s: failed to copy downcall.\n", __func__); 411 412 goto Efault; 412 413 } ··· 459 462 goto Enomem; 460 463 } 461 464 memset(op->downcall.trailer_buf, 0, op->downcall.trailer_size); 462 - n = copy_from_iter(op->downcall.trailer_buf, 463 - op->downcall.trailer_size, 464 - iter); 465 - if (n != op->downcall.trailer_size) { 465 + if (!copy_from_iter_full(op->downcall.trailer_buf, 466 + op->downcall.trailer_size, iter)) { 466 467 gossip_err("%s: failed to copy trailer.\n", __func__); 467 468 vfree(op->downcall.trailer_buf); 468 469 goto Efault;
+3
include/linux/uio.h
··· 89 89 struct iov_iter *i); 90 90 size_t copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i); 91 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 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 95 size_t iov_iter_zero(size_t bytes, struct iov_iter *); 94 96 unsigned long iov_iter_alignment(const struct iov_iter *i); 95 97 unsigned long iov_iter_gap_alignment(const struct iov_iter *i); ··· 157 155 } 158 156 size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); 159 157 size_t csum_and_copy_from_iter(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); 158 + bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct iov_iter *i); 160 159 161 160 int import_iovec(int type, const struct iovec __user * uvector, 162 161 unsigned nr_segs, unsigned fast_segs,
+1 -1
kernel/printk/printk.c
··· 748 748 return -ENOMEM; 749 749 750 750 buf[len] = '\0'; 751 - if (copy_from_iter(buf, len, from) != len) { 751 + if (!copy_from_iter_full(buf, len, from)) { 752 752 kfree(buf); 753 753 return -EFAULT; 754 754 }
+96 -2
lib/iov_iter.c
··· 568 568 } 569 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 596 size_t copy_from_iter_nocache(void *addr, size_t bytes, struct iov_iter *i) 572 597 { 573 598 char *to = addr; ··· 611 586 return bytes; 612 587 } 613 588 EXPORT_SYMBOL(copy_from_iter_nocache); 589 + 590 + bool copy_from_iter_full_nocache(void *addr, size_t bytes, struct iov_iter *i) 591 + { 592 + char *to = addr; 593 + if (unlikely(i->type & ITER_PIPE)) { 594 + WARN_ON(1); 595 + return false; 596 + } 597 + if (unlikely(i->count < bytes)) \ 598 + return false; 599 + iterate_all_kinds(i, bytes, v, ({ 600 + if (__copy_from_user_nocache((to += v.iov_len) - v.iov_len, 601 + v.iov_base, v.iov_len)) 602 + return false; 603 + 0;}), 604 + memcpy_from_page((to += v.bv_len) - v.bv_len, v.bv_page, 605 + v.bv_offset, v.bv_len), 606 + memcpy((to += v.iov_len) - v.iov_len, v.iov_base, v.iov_len) 607 + ) 608 + 609 + iov_iter_advance(i, bytes); 610 + return true; 611 + } 612 + EXPORT_SYMBOL(copy_from_iter_full_nocache); 614 613 615 614 size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, 616 615 struct iov_iter *i) ··· 1057 1008 } 1058 1009 iterate_and_advance(i, bytes, v, ({ 1059 1010 int err = 0; 1060 - next = csum_and_copy_from_user(v.iov_base, 1011 + next = csum_and_copy_from_user(v.iov_base, 1061 1012 (to += v.iov_len) - v.iov_len, 1062 1013 v.iov_len, 0, &err); 1063 1014 if (!err) { ··· 1086 1037 } 1087 1038 EXPORT_SYMBOL(csum_and_copy_from_iter); 1088 1039 1040 + bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, 1041 + struct iov_iter *i) 1042 + { 1043 + char *to = addr; 1044 + __wsum sum, next; 1045 + size_t off = 0; 1046 + sum = *csum; 1047 + if (unlikely(i->type & ITER_PIPE)) { 1048 + WARN_ON(1); 1049 + return false; 1050 + } 1051 + if (unlikely(i->count < bytes)) 1052 + return false; 1053 + iterate_all_kinds(i, bytes, v, ({ 1054 + int err = 0; 1055 + next = csum_and_copy_from_user(v.iov_base, 1056 + (to += v.iov_len) - v.iov_len, 1057 + v.iov_len, 0, &err); 1058 + if (err) 1059 + return false; 1060 + sum = csum_block_add(sum, next, off); 1061 + off += v.iov_len; 1062 + 0; 1063 + }), ({ 1064 + char *p = kmap_atomic(v.bv_page); 1065 + next = csum_partial_copy_nocheck(p + v.bv_offset, 1066 + (to += v.bv_len) - v.bv_len, 1067 + v.bv_len, 0); 1068 + kunmap_atomic(p); 1069 + sum = csum_block_add(sum, next, off); 1070 + off += v.bv_len; 1071 + }),({ 1072 + next = csum_partial_copy_nocheck(v.iov_base, 1073 + (to += v.iov_len) - v.iov_len, 1074 + v.iov_len, 0); 1075 + sum = csum_block_add(sum, next, off); 1076 + off += v.iov_len; 1077 + }) 1078 + ) 1079 + *csum = sum; 1080 + iov_iter_advance(i, bytes); 1081 + return true; 1082 + } 1083 + EXPORT_SYMBOL(csum_and_copy_from_iter_full); 1084 + 1089 1085 size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum, 1090 1086 struct iov_iter *i) 1091 1087 { ··· 1145 1051 iterate_and_advance(i, bytes, v, ({ 1146 1052 int err = 0; 1147 1053 next = csum_and_copy_to_user((from += v.iov_len) - v.iov_len, 1148 - v.iov_base, 1054 + v.iov_base, 1149 1055 v.iov_len, 0, &err); 1150 1056 if (!err) { 1151 1057 sum = csum_block_add(sum, next, off);
+1 -1
net/atm/common.c
··· 630 630 goto out; 631 631 skb->dev = NULL; /* for paths shared with net_device interfaces */ 632 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 634 kfree_skb(skb); 635 635 error = -EFAULT; 636 636 goto out;
+3 -3
net/bluetooth/l2cap_core.c
··· 2127 2127 struct sk_buff **frag; 2128 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 2131 return -EFAULT; 2132 2132 2133 2133 sent += count; ··· 2147 2147 2148 2148 *frag = tmp; 2149 2149 2150 - if (copy_from_iter(skb_put(*frag, count), count, 2151 - &msg->msg_iter) != count) 2150 + if (!copy_from_iter_full(skb_put(*frag, count), count, 2151 + &msg->msg_iter)) 2152 2152 return -EFAULT; 2153 2153 2154 2154 sent += count;
+1 -4
net/packet/af_packet.c
··· 2432 2432 static int packet_snd_vnet_parse(struct msghdr *msg, size_t *len, 2433 2433 struct virtio_net_hdr *vnet_hdr) 2434 2434 { 2435 - int n; 2436 - 2437 2435 if (*len < sizeof(*vnet_hdr)) 2438 2436 return -EINVAL; 2439 2437 *len -= sizeof(*vnet_hdr); 2440 2438 2441 - n = copy_from_iter(vnet_hdr, sizeof(*vnet_hdr), &msg->msg_iter); 2442 - if (n != sizeof(*vnet_hdr)) 2439 + if (!copy_from_iter_full(vnet_hdr, sizeof(*vnet_hdr), &msg->msg_iter)) 2443 2440 return -EFAULT; 2444 2441 2445 2442 return __packet_snd_vnet_parse(vnet_hdr, *len);
+2 -2
net/tipc/msg.c
··· 268 268 __skb_queue_tail(list, skb); 269 269 skb_copy_to_linear_data(skb, mhdr, mhsz); 270 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 272 return dsz; 273 273 rc = -EFAULT; 274 274 goto error; ··· 299 299 if (drem < pktrem) 300 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 303 rc = -EFAULT; 304 304 goto error; 305 305 }
+1 -1
security/keys/keyctl.c
··· 1074 1074 } 1075 1075 1076 1076 ret = -EFAULT; 1077 - if (copy_from_iter(payload, plen, from) != plen) 1077 + if (!copy_from_iter_full(payload, plen, from)) 1078 1078 goto error2; 1079 1079 } 1080 1080