From: Patrick McHardy Date: Wed, 15 Nov 2006 03:48:09 +0000 (-0800) Subject: [NETFILTER]: Use pskb_trim in {ip,ip6,nfnetlink}_queue X-Git-Tag: v2.6.19~87^2~4 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d8a585d78efdf191a64ca655136ac1e49fd27cf4;p=linux-2.6 [NETFILTER]: Use pskb_trim in {ip,ip6,nfnetlink}_queue Based on patch by James D. Nurmi: I've got some code very dependant on nfnetlink_queue, and turned up a large number of warns coming from skb_trim. While it's quite possibly my code, having not seen it on older kernels made me a bit suspect. Anyhow, based on some googling I turned up this thread: http://lkml.org/lkml/2006/8/13/56 And believe the issue to be related, so attached is a small patch to the kernel -- not sure if this is completely correct, but for anyone else hitting the WARN_ON(1) in skbuff.h, it might be helpful.. Signed-off-by: James D. Nurmi Ported to ip6_queue and nfnetlink_queue and added return value checks. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 7edad79047..97556cc2e4 100644 --- a/net/ipv4/netfilter/ip_queue.c +++ b/net/ipv4/netfilter/ip_queue.c @@ -351,9 +351,10 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) if (v->data_len < sizeof(*user_iph)) return 0; diff = v->data_len - e->skb->len; - if (diff < 0) - skb_trim(e->skb, v->data_len); - else if (diff > 0) { + if (diff < 0) { + if (pskb_trim(e->skb, v->data_len)) + return -ENOMEM; + } else if (diff > 0) { if (v->data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 9510c24ca8..9fec832ee0 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c @@ -349,9 +349,10 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e) if (v->data_len < sizeof(*user_iph)) return 0; diff = v->data_len - e->skb->len; - if (diff < 0) - skb_trim(e->skb, v->data_len); - else if (diff > 0) { + if (diff < 0) { + if (pskb_trim(e->skb, v->data_len)) + return -ENOMEM; + } else if (diff > 0) { if (v->data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) { diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 6e4ada3c18..e815a9aa6e 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -622,9 +622,10 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e) int diff; diff = data_len - e->skb->len; - if (diff < 0) - skb_trim(e->skb, data_len); - else if (diff > 0) { + if (diff < 0) { + if (pskb_trim(e->skb, data_len)) + return -ENOMEM; + } else if (diff > 0) { if (data_len > 0xFFFF) return -EINVAL; if (diff > skb_tailroom(e->skb)) {