From 690bf96392f81b9b80c25a15e0b3183b74937702 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 24 Nov 2003 03:44:51 -0800 Subject: [PATCH] [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 --- include/net/sock.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index 22801b214d982..ac2eccb7ff9aa 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -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) { int err = 0; + int skb_len; /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces 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) skb->dev = NULL; 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); + if (!sock_flag(sk, SOCK_DEAD)) - sk->sk_data_ready(sk, skb->len); + sk->sk_data_ready(sk, skb_len); out: return err; } -- 2.53.0