From: Stefano Garzarella <[email protected]>
virtio_transport_init_zcopy_skb() uses iter->count as the size argument
for msg_zerocopy_realloc(), which in turn passes it to
mm_account_pinned_pages() for RLIMIT_MEMLOCK accounting. However, this
function is called after virtio_transport_fill_skb() has already consumed
the iterator via __zerocopy_sg_from_iter(), so on the last skb, iter->count
will be 0, skipping the RLIMIT_MEMLOCK enforcement.
Pass pkt_len (the total bytes being sent) as an explicit parameter to
virtio_transport_init_zcopy_skb() instead of reading the already-consumed
iter->count.
This matches TCP and UDP, which both call msg_zerocopy_realloc() with
the original message size.
Fixes: 581512a6dc93 ("vsock/virtio: MSG_ZEROCOPY flag support")
Reported-by: Yiming Qian <[email protected]>
Signed-off-by: Stefano Garzarella <[email protected]>
---
net/vmw_vsock/virtio_transport_common.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/net/vmw_vsock/virtio_transport_common.c
b/net/vmw_vsock/virtio_transport_common.c
index 0742091beae7..416d533f493d 100644
--- a/net/vmw_vsock/virtio_transport_common.c
+++ b/net/vmw_vsock/virtio_transport_common.c
@@ -73,6 +73,7 @@ static bool virtio_transport_can_zcopy(const struct
virtio_transport *t_ops,
static int virtio_transport_init_zcopy_skb(struct vsock_sock *vsk,
struct sk_buff *skb,
struct msghdr *msg,
+ size_t pkt_len,
bool zerocopy)
{
struct ubuf_info *uarg;
@@ -81,12 +82,10 @@ static int virtio_transport_init_zcopy_skb(struct
vsock_sock *vsk,
uarg = msg->msg_ubuf;
net_zcopy_get(uarg);
} else {
- struct iov_iter *iter = &msg->msg_iter;
struct ubuf_info_msgzc *uarg_zc;
uarg = msg_zerocopy_realloc(sk_vsock(vsk),
- iter->count,
- NULL, false);
+ pkt_len, NULL, false);
if (!uarg)
return -1;
@@ -398,11 +397,17 @@ static int virtio_transport_send_pkt_info(struct
vsock_sock *vsk,
* each iteration. If this is last skb for this buffer
* and MSG_ZEROCOPY mode is in use - we must allocate
* completion for the current syscall.
+ *
+ * Pass pkt_len because msg iter is already consumed
+ * by virtio_transport_fill_skb(), so iter->count
+ * can not be used for RLIMIT_MEMLOCK pinned-pages
+ * accounting done by msg_zerocopy_realloc().
*/
if (info->msg && info->msg->msg_flags & MSG_ZEROCOPY &&
skb_len == rest_len && info->op == VIRTIO_VSOCK_OP_RW) {
if (virtio_transport_init_zcopy_skb(vsk, skb,
info->msg,
+ pkt_len,
can_zcopy)) {
kfree_skb(skb);
ret = -ENOMEM;
--
2.53.0