Message ID | 20190607215748.146484-1-willemdebruijn.kernel@gmail.com |
---|---|
State | Accepted |
Delegated to: | David Miller |
Headers | show |
Series | [net] net: correct udp zerocopy refcnt also when zerocopy only on append | expand |
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com> Date: Fri, 7 Jun 2019 17:57:48 -0400 > From: Willem de Bruijn <willemb@google.com> > > The below patch fixes an incorrect zerocopy refcnt increment when > appending with MSG_MORE to an existing zerocopy udp skb. > > send(.., MSG_ZEROCOPY | MSG_MORE); // refcnt 1 > send(.., MSG_ZEROCOPY | MSG_MORE); // refcnt still 1 (bar frags) > > But it missed that zerocopy need not be passed at the first send. The > right test whether the uarg is newly allocated and thus has extra > refcnt 1 is not !skb, but !skb_zcopy. > > send(.., MSG_MORE); // <no uarg> > send(.., MSG_ZEROCOPY); // refcnt 1 > > Fixes: 100f6d8e09905 ("net: correct zerocopy refcnt with udp MSG_MORE") > Reported-by: syzbot <syzkaller@googlegroups.com> > Signed-off-by: Willem de Bruijn <willemb@google.com> Applied, thanks Willem.
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8c9189a41b136..16f9159234a20 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -918,7 +918,7 @@ static int __ip_append_data(struct sock *sk, uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb)); if (!uarg) return -ENOBUFS; - extra_uref = !skb; /* only extra ref if !MSG_MORE */ + extra_uref = !skb_zcopy(skb); /* only ref on new uarg */ if (rt->dst.dev->features & NETIF_F_SG && csummode == CHECKSUM_PARTIAL) { paged = true; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 934c88f128abb..834475717110e 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1340,7 +1340,7 @@ static int __ip6_append_data(struct sock *sk, uarg = sock_zerocopy_realloc(sk, length, skb_zcopy(skb)); if (!uarg) return -ENOBUFS; - extra_uref = !skb; /* only extra ref if !MSG_MORE */ + extra_uref = !skb_zcopy(skb); /* only ref on new uarg */ if (rt->dst.dev->features & NETIF_F_SG && csummode == CHECKSUM_PARTIAL) { paged = true;