aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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/ipv4
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/ipv4')
-rw-r--r--net/ipv4/netfilter/ip_queue.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 6bda1102851..fe05da41d6b 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -283,8 +283,8 @@ static int
283ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e) 283ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
284{ 284{
285 int diff; 285 int diff;
286 int err;
287 struct iphdr *user_iph = (struct iphdr *)v->payload; 286 struct iphdr *user_iph = (struct iphdr *)v->payload;
287 struct sk_buff *nskb;
288 288
289 if (v->data_len < sizeof(*user_iph)) 289 if (v->data_len < sizeof(*user_iph))
290 return 0; 290 return 0;
@@ -296,14 +296,16 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct nf_queue_entry *e)
296 if (v->data_len > 0xFFFF) 296 if (v->data_len > 0xFFFF)
297 return -EINVAL; 297 return -EINVAL;
298 if (diff > skb_tailroom(e->skb)) { 298 if (diff > skb_tailroom(e->skb)) {
299 err = pskb_expand_head(e->skb, 0, 299 nskb = skb_copy_expand(e->skb, 0,
300 diff - skb_tailroom(e->skb), 300 diff - skb_tailroom(e->skb),
301 GFP_ATOMIC); 301 GFP_ATOMIC);
302 if (err) { 302 if (!nskb) {
303 printk(KERN_WARNING "ip_queue: error " 303 printk(KERN_WARNING "ip_queue: error "
304 "in mangle, dropping packet: %d\n", -err); 304 "in mangle, dropping packet\n");
305 return err; 305 return -ENOMEM;
306 } 306 }
307 kfree_skb(e->skb);
308 e->skb = nskb;
307 } 309 }
308 skb_put(e->skb, diff); 310 skb_put(e->skb, diff);
309 } 311 }