aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-02-19 20:17:52 -0500
committerDavid S. Miller <davem@davemloft.net>2008-02-19 20:17:52 -0500
commite2b58a67b91dec07dfb40ca2056c64011ce8489d (patch)
tree46e258092c2401b9cf6bc232ecfe96248a51982e /net/netfilter
parent94cb1503c799c0197e7ef5bad606fee5c84b99d8 (diff)
[NETFILTER]: {ip,ip6,nfnetlink}_queue: fix SKB_LINEAR_ASSERT when mangling packet data
As reported by Tomas Simonaitis <tomas.simonaitis@gmail.com>, inserting new data in skbs queued over {ip,ip6,nfnetlink}_queue triggers a SKB_LINEAR_ASSERT in skb_put(). Going back through the git history, it seems this bug is present since at least 2.6.12-rc2, probably even since the removal of skb_linearize() for netfilter. Linearize non-linear skbs through skb_copy_expand() when enlarging them. Tested by Thomas, fixes bugzilla #9933. Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/nfnetlink_queue.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index a48b20fe9cd..0043d3a9f87 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -443,8 +443,8 @@ err_out:
443static int 443static int
444nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e) 444nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e)
445{ 445{
446 struct sk_buff *nskb;
446 int diff; 447 int diff;
447 int err;
448 448
449 diff = data_len - e->skb->len; 449 diff = data_len - e->skb->len;
450 if (diff < 0) { 450 if (diff < 0) {
@@ -454,14 +454,16 @@ nfqnl_mangle(void *data, int data_len, struct nf_queue_entry *e)
454 if (data_len > 0xFFFF) 454 if (data_len > 0xFFFF)
455 return -EINVAL; 455 return -EINVAL;
456 if (diff > skb_tailroom(e->skb)) { 456 if (diff > skb_tailroom(e->skb)) {
457 err = pskb_expand_head(e->skb, 0, 457 nskb = skb_copy_expand(e->skb, 0,
458 diff - skb_tailroom(e->skb), 458 diff - skb_tailroom(e->skb),
459 GFP_ATOMIC); 459 GFP_ATOMIC);
460 if (err) { 460 if (!nskb) {
461 printk(KERN_WARNING "nf_queue: OOM " 461 printk(KERN_WARNING "nf_queue: OOM "
462 "in mangle, dropping packet\n"); 462 "in mangle, dropping packet\n");
463 return err; 463 return -ENOMEM;
464 } 464 }
465 kfree_skb(e->skb);
466 e->skb = nskb;
465 } 467 }
466 skb_put(e->skb, diff); 468 skb_put(e->skb, diff);
467 } 469 }