mirror of
https://github.com/torvalds/linux.git
synced 2026-06-05 04:56:13 +02:00
vsock/virtio: fix MSG_ZEROCOPY pinned-pages accounting
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: 581512a6dc ("vsock/virtio: MSG_ZEROCOPY flag support")
Reported-by: Yiming Qian <yimingqian591@gmail.com>
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Reviewed-by: Bobby Eshleman <bobbyeshleman@meta.com>
Link: https://patch.msgid.link/20260420132051.217589-1-sgarzare@redhat.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
42ea37b077
commit
1cb36e2522
|
|
@ -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,
|
static int virtio_transport_init_zcopy_skb(struct vsock_sock *vsk,
|
||||||
struct sk_buff *skb,
|
struct sk_buff *skb,
|
||||||
struct msghdr *msg,
|
struct msghdr *msg,
|
||||||
|
size_t pkt_len,
|
||||||
bool zerocopy)
|
bool zerocopy)
|
||||||
{
|
{
|
||||||
struct ubuf_info *uarg;
|
struct ubuf_info *uarg;
|
||||||
|
|
@ -81,12 +82,10 @@ static int virtio_transport_init_zcopy_skb(struct vsock_sock *vsk,
|
||||||
uarg = msg->msg_ubuf;
|
uarg = msg->msg_ubuf;
|
||||||
net_zcopy_get(uarg);
|
net_zcopy_get(uarg);
|
||||||
} else {
|
} else {
|
||||||
struct iov_iter *iter = &msg->msg_iter;
|
|
||||||
struct ubuf_info_msgzc *uarg_zc;
|
struct ubuf_info_msgzc *uarg_zc;
|
||||||
|
|
||||||
uarg = msg_zerocopy_realloc(sk_vsock(vsk),
|
uarg = msg_zerocopy_realloc(sk_vsock(vsk),
|
||||||
iter->count,
|
pkt_len, NULL, false);
|
||||||
NULL, false);
|
|
||||||
if (!uarg)
|
if (!uarg)
|
||||||
return -1;
|
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
|
* each iteration. If this is last skb for this buffer
|
||||||
* and MSG_ZEROCOPY mode is in use - we must allocate
|
* and MSG_ZEROCOPY mode is in use - we must allocate
|
||||||
* completion for the current syscall.
|
* 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 &&
|
if (info->msg && info->msg->msg_flags & MSG_ZEROCOPY &&
|
||||||
skb_len == rest_len && info->op == VIRTIO_VSOCK_OP_RW) {
|
skb_len == rest_len && info->op == VIRTIO_VSOCK_OP_RW) {
|
||||||
if (virtio_transport_init_zcopy_skb(vsk, skb,
|
if (virtio_transport_init_zcopy_skb(vsk, skb,
|
||||||
info->msg,
|
info->msg,
|
||||||
|
pkt_len,
|
||||||
can_zcopy)) {
|
can_zcopy)) {
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user