aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-10-14 03:39:18 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-15 15:26:27 -0400
commit37d41879224108d6c24578ba6a3eeafce106ce84 (patch)
tree96eb40eb2be71feef1c675800662084be14b2e96 /net
parent7b995651e373d6424f81db23f2ec503306dfd7f0 (diff)
[NETFILTER]: Do not copy skb in skb_make_writable
Now that all callers of netfilter can guarantee that the skb is not shared, we no longer have to copy the skb in skb_make_writable. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/ip_queue.c2
-rw-r--r--net/ipv4/netfilter/ipt_ECN.c4
-rw-r--r--net/ipv4/netfilter/ipt_TOS.c2
-rw-r--r--net/ipv4/netfilter/ipt_TTL.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c4
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c8
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_gre.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_icmp.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_tcp.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_udp.c2
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c2
-rw-r--r--net/ipv6/netfilter/ip6_queue.c2
-rw-r--r--net/ipv6/netfilter/ip6t_HL.c2
-rw-r--r--net/netfilter/core.c38
-rw-r--r--net/netfilter/nfnetlink_queue.c2
-rw-r--r--net/netfilter/xt_DSCP.c4
-rw-r--r--net/netfilter/xt_TCPMSS.c2
17 files changed, 36 insertions, 46 deletions
diff --git a/net/ipv4/netfilter/ip_queue.c b/net/ipv4/netfilter/ip_queue.c
index 23cbfc7c80fd..62d8867ca7d0 100644
--- a/net/ipv4/netfilter/ip_queue.c
+++ b/net/ipv4/netfilter/ip_queue.c
@@ -365,7 +365,7 @@ ipq_mangle_ipv4(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
365 } 365 }
366 skb_put(e->skb, diff); 366 skb_put(e->skb, diff);
367 } 367 }
368 if (!skb_make_writable(&e->skb, v->data_len)) 368 if (!skb_make_writable(e->skb, v->data_len))
369 return -ENOMEM; 369 return -ENOMEM;
370 skb_copy_to_linear_data(e->skb, v->payload, v->data_len); 370 skb_copy_to_linear_data(e->skb, v->payload, v->data_len);
371 e->skb->ip_summed = CHECKSUM_NONE; 371 e->skb->ip_summed = CHECKSUM_NONE;
diff --git a/net/ipv4/netfilter/ipt_ECN.c b/net/ipv4/netfilter/ipt_ECN.c
index f1253bd3837f..92744be1c55e 100644
--- a/net/ipv4/netfilter/ipt_ECN.c
+++ b/net/ipv4/netfilter/ipt_ECN.c
@@ -32,7 +32,7 @@ set_ect_ip(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
32 32
33 if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) { 33 if ((iph->tos & IPT_ECN_IP_MASK) != (einfo->ip_ect & IPT_ECN_IP_MASK)) {
34 __u8 oldtos; 34 __u8 oldtos;
35 if (!skb_make_writable(pskb, sizeof(struct iphdr))) 35 if (!skb_make_writable(*pskb, sizeof(struct iphdr)))
36 return false; 36 return false;
37 iph = ip_hdr(*pskb); 37 iph = ip_hdr(*pskb);
38 oldtos = iph->tos; 38 oldtos = iph->tos;
@@ -62,7 +62,7 @@ set_ect_tcp(struct sk_buff **pskb, const struct ipt_ECN_info *einfo)
62 tcph->cwr == einfo->proto.tcp.cwr)) 62 tcph->cwr == einfo->proto.tcp.cwr))
63 return true; 63 return true;
64 64
65 if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) 65 if (!skb_make_writable(*pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
66 return false; 66 return false;
67 tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb); 67 tcph = (void *)ip_hdr(*pskb) + ip_hdrlen(*pskb);
68 68
diff --git a/net/ipv4/netfilter/ipt_TOS.c b/net/ipv4/netfilter/ipt_TOS.c
index 25f5d0b39065..87b689ac09a5 100644
--- a/net/ipv4/netfilter/ipt_TOS.c
+++ b/net/ipv4/netfilter/ipt_TOS.c
@@ -33,7 +33,7 @@ target(struct sk_buff **pskb,
33 33
34 if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) { 34 if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
35 __u8 oldtos; 35 __u8 oldtos;
36 if (!skb_make_writable(pskb, sizeof(struct iphdr))) 36 if (!skb_make_writable(*pskb, sizeof(struct iphdr)))
37 return NF_DROP; 37 return NF_DROP;
38 iph = ip_hdr(*pskb); 38 iph = ip_hdr(*pskb);
39 oldtos = iph->tos; 39 oldtos = iph->tos;
diff --git a/net/ipv4/netfilter/ipt_TTL.c b/net/ipv4/netfilter/ipt_TTL.c
index 2b54e7b0cfe8..3dd467611e11 100644
--- a/net/ipv4/netfilter/ipt_TTL.c
+++ b/net/ipv4/netfilter/ipt_TTL.c
@@ -29,7 +29,7 @@ ipt_ttl_target(struct sk_buff **pskb,
29 const struct ipt_TTL_info *info = targinfo; 29 const struct ipt_TTL_info *info = targinfo;
30 int new_ttl; 30 int new_ttl;
31 31
32 if (!skb_make_writable(pskb, (*pskb)->len)) 32 if (!skb_make_writable(*pskb, (*pskb)->len))
33 return NF_DROP; 33 return NF_DROP;
34 34
35 iph = ip_hdr(*pskb); 35 iph = ip_hdr(*pskb);
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 7221aa20e6ff..3b5eb7c1a13c 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -357,7 +357,7 @@ manip_pkt(u_int16_t proto,
357 struct iphdr *iph; 357 struct iphdr *iph;
358 struct nf_nat_protocol *p; 358 struct nf_nat_protocol *p;
359 359
360 if (!skb_make_writable(pskb, iphdroff + sizeof(*iph))) 360 if (!skb_make_writable(*pskb, iphdroff + sizeof(*iph)))
361 return 0; 361 return 0;
362 362
363 iph = (void *)(*pskb)->data + iphdroff; 363 iph = (void *)(*pskb)->data + iphdroff;
@@ -431,7 +431,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct,
431 unsigned long statusbit; 431 unsigned long statusbit;
432 enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); 432 enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
433 433
434 if (!skb_make_writable(pskb, hdrlen + sizeof(*inside))) 434 if (!skb_make_writable(*pskb, hdrlen + sizeof(*inside)))
435 return 0; 435 return 0;
436 436
437 inside = (void *)(*pskb)->data + ip_hdrlen(*pskb); 437 inside = (void *)(*pskb)->data + ip_hdrlen(*pskb);
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 93d8a0a8f035..6e81f7612b71 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -152,7 +152,7 @@ nf_nat_mangle_tcp_packet(struct sk_buff **pskb,
152 struct tcphdr *tcph; 152 struct tcphdr *tcph;
153 int oldlen, datalen; 153 int oldlen, datalen;
154 154
155 if (!skb_make_writable(pskb, (*pskb)->len)) 155 if (!skb_make_writable(*pskb, (*pskb)->len))
156 return 0; 156 return 0;
157 157
158 if (rep_len > match_len && 158 if (rep_len > match_len &&
@@ -234,7 +234,7 @@ nf_nat_mangle_udp_packet(struct sk_buff **pskb,
234 match_offset + match_len) 234 match_offset + match_len)
235 return 0; 235 return 0;
236 236
237 if (!skb_make_writable(pskb, (*pskb)->len)) 237 if (!skb_make_writable(*pskb, (*pskb)->len))
238 return 0; 238 return 0;
239 239
240 if (rep_len > match_len && 240 if (rep_len > match_len &&
@@ -341,7 +341,7 @@ nf_nat_sack_adjust(struct sk_buff **pskb,
341 optoff = ip_hdrlen(*pskb) + sizeof(struct tcphdr); 341 optoff = ip_hdrlen(*pskb) + sizeof(struct tcphdr);
342 optend = ip_hdrlen(*pskb) + tcph->doff * 4; 342 optend = ip_hdrlen(*pskb) + tcph->doff * 4;
343 343
344 if (!skb_make_writable(pskb, optend)) 344 if (!skb_make_writable(*pskb, optend))
345 return 0; 345 return 0;
346 346
347 dir = CTINFO2DIR(ctinfo); 347 dir = CTINFO2DIR(ctinfo);
@@ -390,7 +390,7 @@ nf_nat_seq_adjust(struct sk_buff **pskb,
390 this_way = &nat->seq[dir]; 390 this_way = &nat->seq[dir];
391 other_way = &nat->seq[!dir]; 391 other_way = &nat->seq[!dir];
392 392
393 if (!skb_make_writable(pskb, ip_hdrlen(*pskb) + sizeof(*tcph))) 393 if (!skb_make_writable(*pskb, ip_hdrlen(*pskb) + sizeof(*tcph)))
394 return 0; 394 return 0;
395 395
396 tcph = (void *)(*pskb)->data + ip_hdrlen(*pskb); 396 tcph = (void *)(*pskb)->data + ip_hdrlen(*pskb);
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c
index d562290b1820..e7a2aafcce5b 100644
--- a/net/ipv4/netfilter/nf_nat_proto_gre.c
+++ b/net/ipv4/netfilter/nf_nat_proto_gre.c
@@ -109,7 +109,7 @@ gre_manip_pkt(struct sk_buff **pskb, unsigned int iphdroff,
109 109
110 /* pgreh includes two optional 32bit fields which are not required 110 /* pgreh includes two optional 32bit fields which are not required
111 * to be there. That's where the magic '8' comes from */ 111 * to be there. That's where the magic '8' comes from */
112 if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh) - 8)) 112 if (!skb_make_writable(*pskb, hdroff + sizeof(*pgreh) - 8))
113 return 0; 113 return 0;
114 114
115 greh = (void *)(*pskb)->data + hdroff; 115 greh = (void *)(*pskb)->data + hdroff;
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c
index 898d73771155..4087f4f42c34 100644
--- a/net/ipv4/netfilter/nf_nat_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c
@@ -61,7 +61,7 @@ icmp_manip_pkt(struct sk_buff **pskb,
61 struct icmphdr *hdr; 61 struct icmphdr *hdr;
62 unsigned int hdroff = iphdroff + iph->ihl*4; 62 unsigned int hdroff = iphdroff + iph->ihl*4;
63 63
64 if (!skb_make_writable(pskb, hdroff + sizeof(*hdr))) 64 if (!skb_make_writable(*pskb, hdroff + sizeof(*hdr)))
65 return 0; 65 return 0;
66 66
67 hdr = (struct icmphdr *)((*pskb)->data + hdroff); 67 hdr = (struct icmphdr *)((*pskb)->data + hdroff);
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c
index 5bbbb2acdc70..e544125dc037 100644
--- a/net/ipv4/netfilter/nf_nat_proto_tcp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c
@@ -106,7 +106,7 @@ tcp_manip_pkt(struct sk_buff **pskb,
106 if ((*pskb)->len >= hdroff + sizeof(struct tcphdr)) 106 if ((*pskb)->len >= hdroff + sizeof(struct tcphdr))
107 hdrsize = sizeof(struct tcphdr); 107 hdrsize = sizeof(struct tcphdr);
108 108
109 if (!skb_make_writable(pskb, hdroff + hdrsize)) 109 if (!skb_make_writable(*pskb, hdroff + hdrsize))
110 return 0; 110 return 0;
111 111
112 iph = (struct iphdr *)((*pskb)->data + iphdroff); 112 iph = (struct iphdr *)((*pskb)->data + iphdroff);
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c
index a0af4fd95584..ebe9b42a8e94 100644
--- a/net/ipv4/netfilter/nf_nat_proto_udp.c
+++ b/net/ipv4/netfilter/nf_nat_proto_udp.c
@@ -97,7 +97,7 @@ udp_manip_pkt(struct sk_buff **pskb,
97 __be32 oldip, newip; 97 __be32 oldip, newip;
98 __be16 *portptr, newport; 98 __be16 *portptr, newport;
99 99
100 if (!skb_make_writable(pskb, hdroff + sizeof(*hdr))) 100 if (!skb_make_writable(*pskb, hdroff + sizeof(*hdr)))
101 return 0; 101 return 0;
102 102
103 iph = (struct iphdr *)((*pskb)->data + iphdroff); 103 iph = (struct iphdr *)((*pskb)->data + iphdroff);
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index 6bfcd3a90f08..87011fe806ca 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -1258,7 +1258,7 @@ static int help(struct sk_buff **pskb, unsigned int protoff,
1258 return NF_DROP; 1258 return NF_DROP;
1259 } 1259 }
1260 1260
1261 if (!skb_make_writable(pskb, (*pskb)->len)) 1261 if (!skb_make_writable(*pskb, (*pskb)->len))
1262 return NF_DROP; 1262 return NF_DROP;
1263 1263
1264 spin_lock_bh(&snmp_lock); 1264 spin_lock_bh(&snmp_lock);
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 0473145ac534..d7080dd475ac 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -362,7 +362,7 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
362 } 362 }
363 skb_put(e->skb, diff); 363 skb_put(e->skb, diff);
364 } 364 }
365 if (!skb_make_writable(&e->skb, v->data_len)) 365 if (!skb_make_writable(e->skb, v->data_len))
366 return -ENOMEM; 366 return -ENOMEM;
367 skb_copy_to_linear_data(e->skb, v->payload, v->data_len); 367 skb_copy_to_linear_data(e->skb, v->payload, v->data_len);
368 e->skb->ip_summed = CHECKSUM_NONE; 368 e->skb->ip_summed = CHECKSUM_NONE;
diff --git a/net/ipv6/netfilter/ip6t_HL.c b/net/ipv6/netfilter/ip6t_HL.c
index ad4d94310b87..f76197fc4dcc 100644
--- a/net/ipv6/netfilter/ip6t_HL.c
+++ b/net/ipv6/netfilter/ip6t_HL.c
@@ -29,7 +29,7 @@ static unsigned int ip6t_hl_target(struct sk_buff **pskb,
29 const struct ip6t_HL_info *info = targinfo; 29 const struct ip6t_HL_info *info = targinfo;
30 int new_hl; 30 int new_hl;
31 31
32 if (!skb_make_writable(pskb, (*pskb)->len)) 32 if (!skb_make_writable(*pskb, (*pskb)->len))
33 return NF_DROP; 33 return NF_DROP;
34 34
35 ip6h = ipv6_hdr(*pskb); 35 ip6h = ipv6_hdr(*pskb);
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index a523fa4136ed..2c9e8e3652d0 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -196,34 +196,24 @@ unlock:
196EXPORT_SYMBOL(nf_hook_slow); 196EXPORT_SYMBOL(nf_hook_slow);
197 197
198 198
199int skb_make_writable(struct sk_buff **pskb, unsigned int writable_len) 199int skb_make_writable(struct sk_buff *skb, unsigned int writable_len)
200{ 200{
201 struct sk_buff *nskb; 201 if (writable_len > skb->len)
202
203 if (writable_len > (*pskb)->len)
204 return 0; 202 return 0;
205 203
206 /* Not exclusive use of packet? Must copy. */ 204 /* Not exclusive use of packet? Must copy. */
207 if (skb_cloned(*pskb) && !skb_clone_writable(*pskb, writable_len)) 205 if (!skb_cloned(skb)) {
208 goto copy_skb; 206 if (writable_len <= skb_headlen(skb))
209 if (skb_shared(*pskb)) 207 return 1;
210 goto copy_skb; 208 } else if (skb_clone_writable(skb, writable_len))
211 209 return 1;
212 return pskb_may_pull(*pskb, writable_len); 210
213 211 if (writable_len <= skb_headlen(skb))
214copy_skb: 212 writable_len = 0;
215 nskb = skb_copy(*pskb, GFP_ATOMIC); 213 else
216 if (!nskb) 214 writable_len -= skb_headlen(skb);
217 return 0; 215
218 BUG_ON(skb_is_nonlinear(nskb)); 216 return !!__pskb_pull_tail(skb, writable_len);
219
220 /* Rest of kernel will get very unhappy if we pass it a
221 suddenly-orphaned skbuff */
222 if ((*pskb)->sk)
223 skb_set_owner_w(nskb, (*pskb)->sk);
224 kfree_skb(*pskb);
225 *pskb = nskb;
226 return 1;
227} 217}
228EXPORT_SYMBOL(skb_make_writable); 218EXPORT_SYMBOL(skb_make_writable);
229 219
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 49f0480afe09..6ba98acdd7a2 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -644,7 +644,7 @@ nfqnl_mangle(void *data, int data_len, struct nfqnl_queue_entry *e)
644 } 644 }
645 skb_put(e->skb, diff); 645 skb_put(e->skb, diff);
646 } 646 }
647 if (!skb_make_writable(&e->skb, data_len)) 647 if (!skb_make_writable(e->skb, data_len))
648 return -ENOMEM; 648 return -ENOMEM;
649 skb_copy_to_linear_data(e->skb, data, data_len); 649 skb_copy_to_linear_data(e->skb, data, data_len);
650 e->skb->ip_summed = CHECKSUM_NONE; 650 e->skb->ip_summed = CHECKSUM_NONE;
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c
index 798ab731009d..170661674388 100644
--- a/net/netfilter/xt_DSCP.c
+++ b/net/netfilter/xt_DSCP.c
@@ -36,7 +36,7 @@ static unsigned int target(struct sk_buff **pskb,
36 u_int8_t dscp = ipv4_get_dsfield(ip_hdr(*pskb)) >> XT_DSCP_SHIFT; 36 u_int8_t dscp = ipv4_get_dsfield(ip_hdr(*pskb)) >> XT_DSCP_SHIFT;
37 37
38 if (dscp != dinfo->dscp) { 38 if (dscp != dinfo->dscp) {
39 if (!skb_make_writable(pskb, sizeof(struct iphdr))) 39 if (!skb_make_writable(*pskb, sizeof(struct iphdr)))
40 return NF_DROP; 40 return NF_DROP;
41 41
42 ipv4_change_dsfield(ip_hdr(*pskb), (__u8)(~XT_DSCP_MASK), 42 ipv4_change_dsfield(ip_hdr(*pskb), (__u8)(~XT_DSCP_MASK),
@@ -57,7 +57,7 @@ static unsigned int target6(struct sk_buff **pskb,
57 u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(*pskb)) >> XT_DSCP_SHIFT; 57 u_int8_t dscp = ipv6_get_dsfield(ipv6_hdr(*pskb)) >> XT_DSCP_SHIFT;
58 58
59 if (dscp != dinfo->dscp) { 59 if (dscp != dinfo->dscp) {
60 if (!skb_make_writable(pskb, sizeof(struct ipv6hdr))) 60 if (!skb_make_writable(*pskb, sizeof(struct ipv6hdr)))
61 return NF_DROP; 61 return NF_DROP;
62 62
63 ipv6_change_dsfield(ipv6_hdr(*pskb), (__u8)(~XT_DSCP_MASK), 63 ipv6_change_dsfield(ipv6_hdr(*pskb), (__u8)(~XT_DSCP_MASK),
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index d40f7e4b1289..31b6f9d09822 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -50,7 +50,7 @@ tcpmss_mangle_packet(struct sk_buff **pskb,
50 u16 newmss; 50 u16 newmss;
51 u8 *opt; 51 u8 *opt;
52 52
53 if (!skb_make_writable(pskb, (*pskb)->len)) 53 if (!skb_make_writable(*pskb, (*pskb)->len))
54 return -1; 54 return -1;
55 55
56 tcplen = (*pskb)->len - tcphoff; 56 tcplen = (*pskb)->len - tcphoff;