Commit 690bf963 authored by David S. Miller's avatar David S. Miller Committed by Linus Torvalds

[NET]: In sock_queue_rcv_skb(), do not deref skb->len after it is queued to the socket.

In implementations that use no socket locking, such as RAW sockets,
once we queue the SKB to the socket another cpu can remove the SKB
from the socket queue and free up the SKB making the skb->len access
touch freed memory.

Based upon a report from Burton Windle, kernel bugzilla #937
parent 29c1bc9f
...@@ -917,6 +917,7 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk) ...@@ -917,6 +917,7 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{ {
int err = 0; int err = 0;
int skb_len;
/* Cast skb->rcvbuf to unsigned... It's pointless, but reduces /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
number of warnings when compiling with -W --ANK number of warnings when compiling with -W --ANK
...@@ -937,9 +938,18 @@ static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -937,9 +938,18 @@ static inline int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
skb->dev = NULL; skb->dev = NULL;
skb_set_owner_r(skb, sk); skb_set_owner_r(skb, sk);
/* Cache the SKB length before we tack it onto the receive
* queue. Once it is added it no longer belongs to us and
* may be freed by other threads of control pulling packets
* from the queue.
*/
skb_len = skb->len;
skb_queue_tail(&sk->sk_receive_queue, skb); skb_queue_tail(&sk->sk_receive_queue, skb);
if (!sock_flag(sk, SOCK_DEAD)) if (!sock_flag(sk, SOCK_DEAD))
sk->sk_data_ready(sk, skb->len); sk->sk_data_ready(sk, skb_len);
out: out:
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment