aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
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/ipv6
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/ipv6')
-rw-r--r--net/ipv6/netfilter/ip6_queue.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index e869916b05f1..cc2f9afcf808 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -285,8 +285,8 @@ static int
285ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e) 285ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
286{ 286{
287 int diff; 287 int diff;
288 int err;
289 struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload; 288 struct ipv6hdr *user_iph = (struct ipv6hdr *)v->payload;
289 struct sk_buff *nskb;
290 290
291 if (v->data_len < sizeof(*user_iph)) 291 if (v->data_len < sizeof(*user_iph))
292 return 0; 292 return 0;
@@ -298,14 +298,16 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
298 if (v->data_len > 0xFFFF) 298 if (v->data_len > 0xFFFF)
299 return -EINVAL; 299 return -EINVAL;
300 if (diff > skb_tailroom(e->skb)) { 300 if (diff > skb_tailroom(e->skb)) {
301 err = pskb_expand_head(e->skb, 0, 301 nskb = skb_copy_expand(e->skb, 0,
302 diff - skb_tailroom(e->skb), 302 diff - skb_tailroom(e->skb),
303 GFP_ATOMIC); 303 GFP_ATOMIC);
304 if (err) { 304 if (!nskb) {
305 printk(KERN_WARNING "ip6_queue: OOM " 305 printk(KERN_WARNING "ip6_queue: OOM "
306 "in mangle, dropping packet\n"); 306 "in mangle, dropping packet\n");
307 return err; 307 return -ENOMEM;
308 } 308 }
309 kfree_skb(e->skb);
310 e->skb = nskb;
309 } 311 }
310 skb_put(e->skb, diff); 312 skb_put(e->skb, diff);
311 } 313 }