Netdev List
 help / color / mirror / Atom feed
* [PATCH net v2 1/1] tcp: reject non zerocopy devmem tx
@ 2026-09-04 13:43 Pavel Begunkov
  2026-09-09 13:45 ` netdev-bot+sashiko
  2026-09-10 12:50 ` patchwork-bot+netdevbpf
  0 siblings, 2 replies; 6+ messages in thread
From: Pavel Begunkov @ 2026-09-04 13:43 UTC (permalink / raw)
  To: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, netdev
  Cc: asml.silence, Mina Almasry

Devmem tcp tx doesn't work without zero-copy, however it's not currently
enforced if NETIF_F_SG isn't present. In this case, tcp_sendmsg_locked()
will try the copy path and try to copy data from an iovec which consists
of offsets into the dma-buf and would normally fail. Moreover,
d9c56501c72fd ("net: tcp: block mixing readable and unreadable frags")
relies on that and assumes that the devmem binding is present IFF we're
using the zero-copy path, which can be used to mix net-iov and pages in
a single skb, and break invariants. Let's reject devmem tx without
zero-copy.

Note, the parameter check the patch is modifying is too loose, we can
create an io_uring request with dmabuf_id and all ZC flags, but which
won't have the binding. We replace it with stricter validation.

Fixes: bd61848900bff ("net: devmem: Implement TX path")
Fixes: d9c56501c72fd ("net: tcp: block mixing readable and unreadable frags")
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
---

v2: combine with post ubuf assignment dmabuf_id checks

 net/ipv4/tcp.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index b4237d0e994d..10f58281be17 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1169,8 +1169,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
 			zc = MSG_SPLICE_PAGES;
 	}
 
-	if (!sockc_err && sockc.dmabuf_id &&
-	    (!(flags & MSG_ZEROCOPY) || !sock_flag(sk, SOCK_ZEROCOPY))) {
+	if (!sockc_err && sockc.dmabuf_id && (zc != MSG_ZEROCOPY || !binding)) {
 		err = -EINVAL;
 		goto out_err;
 	}
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH net v2 1/1] tcp: reject non zerocopy devmem tx
@ 2026-09-09 13:45 ` netdev-bot+sashiko
  2026-09-09 15:57   ` Mina Almasry
  0 siblings, 1 reply; 6+ messages in thread
From: netdev-bot+sashiko @ 2026-09-09 13:45 UTC (permalink / raw)
  To: asml.silence; +Cc: davem, edumazet, kuba, pabeni, horms, netdev, almasrymina

Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:

Critical: 0 · High: 1 · Medium: 0 · Low: 0

- [High] Incomplete enforcement: devmem TX can still reach a byte-copy
  path that misinterprets dma-buf offsets as user virtual addresses.

--

tcp: reject non zerocopy devmem tx

The patch replaces the MSG_ZEROCOPY/SOCK_ZEROCOPY test that guards devmem
TX in tcp_sendmsg_locked() with a stricter check that requires the
zero-copy path to actually be in use and the dmabuf binding to have been
obtained.

> diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> index 1c867a3024446..562752352afe4 100644
> --- a/net/ipv4/tcp.c
> +++ b/net/ipv4/tcp.c
> @@ -1169,8 +1169,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
>  			zc = MSG_SPLICE_PAGES;
>  	}
>  
> -	if (!sockc_err && sockc.dmabuf_id &&
> -	    (!(flags & MSG_ZEROCOPY) || !sock_flag(sk, SOCK_ZEROCOPY))) {
> +	if (!sockc_err && sockc.dmabuf_id && (zc != MSG_ZEROCOPY || !binding)) {
>  		err = -EINVAL;
>  		goto out_err;
>  	}

[Severity: High]
Does this check still leave a devmem copy path reachable via TCP Fast
Open?  Right after it, tcp_sendmsg_locked() does:

	if (unlikely(flags & MSG_FASTOPEN ||
		     inet_test_bit(DEFER_CONNECT, sk)) &&
	    !tp->repair) {
		err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size, uarg);

Neither tcp_sendmsg_fastopen() nor tcp_connect()->tcp_send_syn_data()
gets the binding, and tcp_send_syn_data() copies straight out of the
same iterator:

net/ipv4/tcp_output.c:tcp_send_syn_data() {
	...
	space = copy_page_from_iter(pfrag->page, pfrag->offset,
				    space, &fo->data->msg_iter);
	...
	skb_fill_page_desc(syn_data, 0, pfrag->page,
			   pfrag->offset, space);
	...
	skb_zcopy_set(syn_data, fo->uarg, NULL);
}

For a devmem send the iovec entries are dma-buf offsets, not addresses:

net/core/datagram.c:zerocopy_fill_skb_from_devmem() {
	/* Devmem filling works by taking an IOVEC from the user where the
	 * iov_addrs are interpreted as an offset in bytes into the dma-buf to
	 * send from. We do not support other iter types.
	 */
}

So does copy_page_from_iter() here read whatever the caller happens to
have mapped at the numeric value of those offsets, put it into a regular
page frag, advance the iterator past the corresponding dma-buf range,
and then report those bytes back through fo->copied -> copied_syn ->
copied as if they had been sent?

Is the path reachable without MSG_FASTOPEN as well?  tcp_v4_connect()
runs sk_setup_caps(sk, &rt->dst) before tcp_fastopen_defer_connect(), so
with TCP_FASTOPEN_CONNECT the socket has a dst and NETIF_F_SG in
sk_route_caps while DEFER_CONNECT is still set.  A subsequent
sendmsg(MSG_ZEROCOPY) carrying SCM_DEVMEM_DMABUF would then get
zc == MSG_ZEROCOPY and a valid binding from net_devmem_get_binding(),
pass the new check, and land in tcp_send_syn_data().

There also looks to be a second residual route through repair mode.  The
tp->repair branch below reaches tcp_send_rcvq(), which copies from the
same iterator with no binding awareness:

net/ipv4/tcp_input.c:tcp_send_rcvq() {
	...
	err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size);
	...
}

That one needs CAP_NET_ADMIN, so it is less interesting, but it is still
a devmem iterator being byte-copied.

One more detail on the Fast Open case: msg_zerocopy_alloc() skips
accounting for devmem uargs:

net/core/skbuff.c:msg_zerocopy_alloc() {
	...
	if (likely(!devmem) && mm_account_pinned_pages(&uarg->mmp, size)) {
	...
}

so attaching that uarg to a copied page frag in tcp_send_syn_data()
would leave the frag unaccounted too.

Would it make sense to also reject dmabuf_id together with
MSG_FASTOPEN/DEFER_CONNECT and with repair-queue sends, or to teach
those paths about the binding?  The commit message mentions neither, so
it is hard to tell from the changelog whether these were considered,
which also matters for backporting given the two Fixes: tags.

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/fdc2478d8f21268d7078556409887d8e6ba0ad32.1788529053.git.asml.silence%40gmail.com

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net v2 1/1] tcp: reject non zerocopy devmem tx
  2026-09-09 13:45 ` netdev-bot+sashiko
@ 2026-09-09 15:57   ` Mina Almasry
  2026-09-10 12:44     ` Paolo Abeni
  2026-09-10 12:51     ` Pavel Begunkov
  0 siblings, 2 replies; 6+ messages in thread
From: Mina Almasry @ 2026-09-09 15:57 UTC (permalink / raw)
  To: netdev-bot+sashiko
  Cc: asml.silence, davem, edumazet, kuba, pabeni, horms, netdev

On Wed, Sep 9, 2026 at 6:45 AM <netdev-bot+sashiko@kernel.org> wrote:
>
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider:
>
> Critical: 0 · High: 1 · Medium: 0 · Low: 0
>
> - [High] Incomplete enforcement: devmem TX can still reach a byte-copy
>   path that misinterprets dma-buf offsets as user virtual addresses.
>


Sorry, this slipped my inbox the first time around, but now I see the
Sashiko review.

> --
>
> tcp: reject non zerocopy devmem tx
>
> The patch replaces the MSG_ZEROCOPY/SOCK_ZEROCOPY test that guards devmem
> TX in tcp_sendmsg_locked() with a stricter check that requires the
> zero-copy path to actually be in use and the dmabuf binding to have been
> obtained.
>
> > diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
> > index 1c867a3024446..562752352afe4 100644
> > --- a/net/ipv4/tcp.c
> > +++ b/net/ipv4/tcp.c
> > @@ -1169,8 +1169,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
> >                       zc = MSG_SPLICE_PAGES;
> >       }
> >
> > -     if (!sockc_err && sockc.dmabuf_id &&
> > -         (!(flags & MSG_ZEROCOPY) || !sock_flag(sk, SOCK_ZEROCOPY))) {
> > +     if (!sockc_err && sockc.dmabuf_id && (zc != MSG_ZEROCOPY || !binding)) {
> >               err = -EINVAL;
> >               goto out_err;
> >       }
>
> [Severity: High]
> Does this check still leave a devmem copy path reachable via TCP Fast
> Open?  Right after it, tcp_sendmsg_locked() does:
>
>         if (unlikely(flags & MSG_FASTOPEN ||
>                      inet_test_bit(DEFER_CONNECT, sk)) &&
>             !tp->repair) {
>                 err = tcp_sendmsg_fastopen(sk, msg, &copied_syn, size, uarg);
>
> Neither tcp_sendmsg_fastopen() nor tcp_connect()->tcp_send_syn_data()
> gets the binding, and tcp_send_syn_data() copies straight out of the
> same iterator:
>
> net/ipv4/tcp_output.c:tcp_send_syn_data() {
>         ...
>         space = copy_page_from_iter(pfrag->page, pfrag->offset,
>                                     space, &fo->data->msg_iter);
>         ...
>         skb_fill_page_desc(syn_data, 0, pfrag->page,
>                            pfrag->offset, space);
>         ...
>         skb_zcopy_set(syn_data, fo->uarg, NULL);
> }
>
> For a devmem send the iovec entries are dma-buf offsets, not addresses:
>
> net/core/datagram.c:zerocopy_fill_skb_from_devmem() {
>         /* Devmem filling works by taking an IOVEC from the user where the
>          * iov_addrs are interpreted as an offset in bytes into the dma-buf to
>          * send from. We do not support other iter types.
>          */
> }
>
> So does copy_page_from_iter() here read whatever the caller happens to
> have mapped at the numeric value of those offsets, put it into a regular
> page frag, advance the iterator past the corresponding dma-buf range,
> and then report those bytes back through fo->copied -> copied_syn ->
> copied as if they had been sent?
>
> Is the path reachable without MSG_FASTOPEN as well?  tcp_v4_connect()
> runs sk_setup_caps(sk, &rt->dst) before tcp_fastopen_defer_connect(), so
> with TCP_FASTOPEN_CONNECT the socket has a dst and NETIF_F_SG in
> sk_route_caps while DEFER_CONNECT is still set.  A subsequent
> sendmsg(MSG_ZEROCOPY) carrying SCM_DEVMEM_DMABUF would then get
> zc == MSG_ZEROCOPY and a valid binding from net_devmem_get_binding(),
> pass the new check, and land in tcp_send_syn_data().
>
> There also looks to be a second residual route through repair mode.  The
> tp->repair branch below reaches tcp_send_rcvq(), which copies from the
> same iterator with no binding awareness:
>
> net/ipv4/tcp_input.c:tcp_send_rcvq() {
>         ...
>         err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size);
>         ...
> }
>
> That one needs CAP_NET_ADMIN, so it is less interesting, but it is still
> a devmem iterator being byte-copied.
>
> One more detail on the Fast Open case: msg_zerocopy_alloc() skips
> accounting for devmem uargs:
>
> net/core/skbuff.c:msg_zerocopy_alloc() {
>         ...
>         if (likely(!devmem) && mm_account_pinned_pages(&uarg->mmp, size)) {
>         ...
> }
>
> so attaching that uarg to a copied page frag in tcp_send_syn_data()
> would leave the frag unaccounted too.
>
> Would it make sense to also reject dmabuf_id together with
> MSG_FASTOPEN/DEFER_CONNECT and with repair-queue sends, or to teach
> those paths about the binding?  The commit message mentions neither, so
> it is hard to tell from the changelog whether these were considered,
> which also matters for backporting given the two Fixes: tags.
>

Yes, I think we'd need to exclude MSG_FASTOPEN and DEFER_CONNECT.
Those are set by the userspace right? So it doesn't matter much if we
don't support them with devmem. Not sure how to correctly exclude
repair-queue sends.

I guess it's pointing to more pre-existing issues :( But this patch on
its own is fine.

Reviewed-by: Mina Almasry <almasrymina@google.com>

I can try to follow up on the other prexisting issues.

-- 
Thanks,
Mina

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net v2 1/1] tcp: reject non zerocopy devmem tx
  2026-09-09 15:57   ` Mina Almasry
@ 2026-09-10 12:44     ` Paolo Abeni
  2026-09-10 12:51     ` Pavel Begunkov
  1 sibling, 0 replies; 6+ messages in thread
From: Paolo Abeni @ 2026-09-10 12:44 UTC (permalink / raw)
  To: Mina Almasry; +Cc: asml.silence, davem, edumazet, kuba, horms, netdev

On 9/9/26 5:57 PM, Mina Almasry wrote:
> On Wed, Sep 9, 2026 at 6:45 AM <netdev-bot+sashiko@kernel.org> wrote:
>> Would it make sense to also reject dmabuf_id together with
>> MSG_FASTOPEN/DEFER_CONNECT and with repair-queue sends, or to teach
>> those paths about the binding?  The commit message mentions neither, so
>> it is hard to tell from the changelog whether these were considered,
>> which also matters for backporting given the two Fixes: tags.
>>
> 
> Yes, I think we'd need to exclude MSG_FASTOPEN and DEFER_CONNECT.
> Those are set by the userspace right? So it doesn't matter much if we
> don't support them with devmem. Not sure how to correctly exclude
> repair-queue sends.
FTR, I agree that the sashiko comments refers to a pre-existing and
different issue that should be addressed separately. I'm actually
quite surprised the model did not mark it as such.

/P


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net v2 1/1] tcp: reject non zerocopy devmem tx
  2026-09-04 13:43 [PATCH net v2 1/1] tcp: reject non zerocopy devmem tx Pavel Begunkov
  2026-09-09 13:45 ` netdev-bot+sashiko
@ 2026-09-10 12:50 ` patchwork-bot+netdevbpf
  1 sibling, 0 replies; 6+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-10 12:50 UTC (permalink / raw)
  To: Pavel Begunkov; +Cc: davem, edumazet, kuba, pabeni, horms, netdev, almasrymina

Hello:

This patch was applied to netdev/net.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Fri,  4 Sep 2026 14:43:07 +0100 you wrote:
> Devmem tcp tx doesn't work without zero-copy, however it's not currently
> enforced if NETIF_F_SG isn't present. In this case, tcp_sendmsg_locked()
> will try the copy path and try to copy data from an iovec which consists
> of offsets into the dma-buf and would normally fail. Moreover,
> d9c56501c72fd ("net: tcp: block mixing readable and unreadable frags")
> relies on that and assumes that the devmem binding is present IFF we're
> using the zero-copy path, which can be used to mix net-iov and pages in
> a single skb, and break invariants. Let's reject devmem tx without
> zero-copy.
> 
> [...]

Here is the summary with links:
  - [net,v2,1/1] tcp: reject non zerocopy devmem tx
    https://git.kernel.org/netdev/net/c/125755776bc6

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH net v2 1/1] tcp: reject non zerocopy devmem tx
  2026-09-09 15:57   ` Mina Almasry
  2026-09-10 12:44     ` Paolo Abeni
@ 2026-09-10 12:51     ` Pavel Begunkov
  1 sibling, 0 replies; 6+ messages in thread
From: Pavel Begunkov @ 2026-09-10 12:51 UTC (permalink / raw)
  To: Mina Almasry, netdev-bot+sashiko
  Cc: davem, edumazet, kuba, pabeni, horms, netdev

On 9/9/26 16:57, Mina Almasry wrote:
> On Wed, Sep 9, 2026 at 6:45 AM <netdev-bot+sashiko@kernel.org> wrote:
...>> so attaching that uarg to a copied page frag in tcp_send_syn_data()
>> would leave the frag unaccounted too.
>>
>> Would it make sense to also reject dmabuf_id together with
>> MSG_FASTOPEN/DEFER_CONNECT and with repair-queue sends, or to teach
>> those paths about the binding?  The commit message mentions neither, so
>> it is hard to tell from the changelog whether these were considered,
>> which also matters for backporting given the two Fixes: tags.
>>
> 
> Yes, I think we'd need to exclude MSG_FASTOPEN and DEFER_CONNECT.
> Those are set by the userspace right? So it doesn't matter much if we
> don't support them with devmem. Not sure how to correctly exclude
> repair-queue sends.

I don't know any other user of socket repair apart from CRIU,
and devmem + CRIU is quite a narrow use case, I doubt they yet
do that, and IIRC they don't support restoring any of the
GPUs state for it to be useful. IOW, failing repair with devmem
payload sounds like an option.

> I guess it's pointing to more pre-existing issues :( But this patch on
> its own is fine.
> 
> Reviewed-by: Mina Almasry <almasrymina@google.com>

Thanks

> I can try to follow up on the other prexisting issues.

Great, then I'll leave it to you

-- 
Pavel Begunkov


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-09-10 12:51 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-04 13:43 [PATCH net v2 1/1] tcp: reject non zerocopy devmem tx Pavel Begunkov
2026-09-09 13:45 ` netdev-bot+sashiko
2026-09-09 15:57   ` Mina Almasry
2026-09-10 12:44     ` Paolo Abeni
2026-09-10 12:51     ` Pavel Begunkov
2026-09-10 12:50 ` patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox