diff options
author | Paolo Abeni <pabeni@redhat.com> | 2017-09-06 14:44:36 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-09-07 20:02:39 -0700 |
commit | ca2c1418efe9f7fe37aa1f355efdf4eb293673ce (patch) | |
tree | e7a5bc57ec2c26469e03fb850b4aa61af43bbe38 /net/ipv4 | |
parent | 5c25f30c93fdc5bf25e62101aeaae7a4f9b421b3 (diff) |
udp: drop head states only when all skb references are gone
After commit 0ddf3fb2c43d ("udp: preserve skb->dst if required
for IP options processing") we clear the skb head state as soon
as the skb carrying them is first processed.
Since the same skb can be processed several times when MSG_PEEK
is used, we can end up lacking the required head states, and
eventually oopsing.
Fix this clearing the skb head state only when processing the
last skb reference.
Reported-by: Eric Dumazet <edumazet@google.com>
Fixes: 0ddf3fb2c43d ("udp: preserve skb->dst if required for IP options processing")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/udp.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index db1c9e78c83c..ef29df8648e4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1397,12 +1397,15 @@ void skb_consume_udp(struct sock *sk, struct sk_buff *skb, int len) unlock_sock_fast(sk, slow); } + if (!skb_unref(skb)) + return; + /* In the more common cases we cleared the head states previously, * see __udp_queue_rcv_skb(). */ if (unlikely(udp_skb_has_head_state(skb))) skb_release_head_state(skb); - consume_stateless_skb(skb); + __consume_stateless_skb(skb); } EXPORT_SYMBOL_GPL(skb_consume_udp); |