Le vendredi 10 février 2012 à 12:48 +0800, 单卫 a écrit : > Latest 2.6.32 stable tree(56) still has same problem. > > > The following two commit should not be queued to 2.6.32? > > b1faf5666438090a4dc4fceac8502edc7788b7e3 > (net: sock_queue_err_skb() dont mess with sk_forward_alloc) > > 2903037400a26e7c0cc93ab75a7d62abfacdf485 > (net: fix sk_forward_alloc corruptions) >
You're right, please Greg, here is the backported patch for 2.6.32.56, once David agreed. Thanks ! [PATCH] net: sock_queue_err_skb() dont mess with sk_forward_alloc) Upstream commit b1faf5666438090a4dc4fceac8502edc7788b7e3 (2.6.35) Depending on commit 2903037400a26e7c0cc93ab75a7d62abfacdf485 (net: fix sk_forward_alloc corruptions) Signed-off-by: Eric Dumazet <[email protected]> --- include/net/sock.h | 15 +-------------- net/core/skbuff.c | 30 ++++++++++++++++++++++++++++++ net/ipv4/udp.c | 4 ++-- 3 files changed, 33 insertions(+), 16 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 9f96394..78adf52 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1354,20 +1354,7 @@ extern void sk_stop_timer(struct sock *sk, struct timer_list* timer); extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); -static inline int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) -{ - /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces - number of warnings when compiling with -W --ANK - */ - if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= - (unsigned)sk->sk_rcvbuf) - return -ENOMEM; - skb_set_owner_r(skb, sk); - skb_queue_tail(&sk->sk_error_queue, skb); - if (!sock_flag(sk, SOCK_DEAD)) - sk->sk_data_ready(sk, skb->len); - return 0; -} +extern int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb); /* * Recover an error report and clear atomically diff --git a/net/core/skbuff.c b/net/core/skbuff.c index a807f8c..025f924 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2977,6 +2977,34 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) } EXPORT_SYMBOL_GPL(skb_cow_data); +static void sock_rmem_free(struct sk_buff *skb) +{ + struct sock *sk = skb->sk; + + atomic_sub(skb->truesize, &sk->sk_rmem_alloc); +} + +/* + * Note: We dont mem charge error packets (no sk_forward_alloc changes) + */ +int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) +{ + if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= + (unsigned)sk->sk_rcvbuf) + return -ENOMEM; + + skb_orphan(skb); + skb->sk = sk; + skb->destructor = sock_rmem_free; + atomic_add(skb->truesize, &sk->sk_rmem_alloc); + + skb_queue_tail(&sk->sk_error_queue, skb); + if (!sock_flag(sk, SOCK_DEAD)) + sk->sk_data_ready(sk, skb->len); + return 0; +} +EXPORT_SYMBOL(sock_queue_err_skb); + void skb_tstamp_tx(struct sk_buff *orig_skb, struct skb_shared_hwtstamps *hwtstamps) { @@ -3008,7 +3036,9 @@ void skb_tstamp_tx(struct sk_buff *orig_skb, memset(serr, 0, sizeof(*serr)); serr->ee.ee_errno = ENOMSG; serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; + err = sock_queue_err_skb(sk, skb); + if (err) kfree_skb(skb); } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 0ac8833..8e28770 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -440,9 +440,9 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) if (!inet->recverr) { if (!harderr || sk->sk_state != TCP_ESTABLISHED) goto out; - } else { + } else ip_icmp_error(sk, skb, err, uh->dest, info, (u8 *)(uh+1)); - } + sk->sk_err = err; sk->sk_error_report(sk); out: -- To unsubscribe from this list: send the line "unsubscribe stable" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
