diff options
author | Patrick McHardy <kaber@trash.net> | 2006-11-14 22:48:09 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-11-16 00:18:48 -0500 |
commit | d8a585d78efdf191a64ca655136ac1e49fd27cf4 (patch) | |
tree | 5effa2c2ec3a46fef6aaee1b7484d10318970d0e /net | |
parent | 7fdeaf68a16f8102659cf1b30f57247d8ccbeef0 (diff) |
[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 <jdnurmi@gmail.com>
Ported to ip6_queue and nfnetlink_queue and added return value
checks.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/ip_queue.c | 7 | ||||
-rw-r--r-- | net/ipv6/netfilter/ip6_queue.c | 7 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue.c | 7 |
3 files changed, 12 insertions, 9 deletions
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c index 7edad790478a..97556cc2e4e0 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) | |||
351 | if (v->data_len < sizeof(*user_iph)) | 351 | if (v->data_len < sizeof(*user_iph)) |
352 | return 0; | 352 | return 0; |
353 | diff = v->data_len - e->skb->len; | 353 | diff = v->data_len - e->skb->len; |
354 | if (diff < 0) | 354 | if (diff < 0) { |
355 | skb_trim(e->skb, v->data_len); | 355 | if (pskb_trim(e->skb, v->data_len)) |
356 | else if (diff > 0) { | 356 | return -ENOMEM; |
357 | } else if (diff > 0) { | ||
357 | if (v->data_len > 0xFFFF) | 358 | if (v->data_len > 0xFFFF) |
358 | return -EINVAL; | 359 | return -EINVAL; |
359 | if (diff > skb_tailroom(e->skb)) { | 360 | if (diff > skb_tailroom(e->skb)) { |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 9510c24ca8d2..9fec832ee08b 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) | |||
349 | if (v->data_len < sizeof(*user_iph)) | 349 | if (v->data_len < sizeof(*user_iph)) |
350 | return 0; | 350 | return 0; |
351 | diff = v->data_len - e->skb->len; | 351 | diff = v->data_len - e->skb->len; |
352 | if (diff < 0) | 352 | if (diff < 0) { |
353 | skb_trim(e->skb, v->data_len); | 353 | if (pskb_trim(e->skb, v->data_len)) |
354 | else if (diff > 0) { | 354 | return -ENOMEM; |
355 | } else if (diff > 0) { | ||
355 | if (v->data_len > 0xFFFF) | 356 | if (v->data_len > 0xFFFF) |
356 | return -EINVAL; | 357 | return -EINVAL; |
357 | if (diff > skb_tailroom(e->skb)) { | 358 | if (diff > skb_tailroom(e->skb)) { |
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 6e4ada3c1844..e815a9aa6e95 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) | |||
622 | int diff; | 622 | int diff; |
623 | 623 | ||
624 | diff = data_len - e->skb->len; | 624 | diff = data_len - e->skb->len; |
625 | if (diff < 0) | 625 | if (diff < 0) { |
626 | skb_trim(e->skb, data_len); | 626 | if (pskb_trim(e->skb, data_len)) |
627 | else if (diff > 0) { | 627 | return -ENOMEM; |
628 | } else if (diff > 0) { | ||
628 | if (data_len > 0xFFFF) | 629 | if (data_len > 0xFFFF) |
629 | return -EINVAL; | 630 | return -EINVAL; |
630 | if (diff > skb_tailroom(e->skb)) { | 631 | if (diff > skb_tailroom(e->skb)) { |