diff options
-rw-r--r-- | drivers/net/pppoe.c | 2 | ||||
-rw-r--r-- | include/linux/skbuff.h | 40 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 2 |
3 files changed, 33 insertions, 11 deletions
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index bac36546e0bf..0d7f570b9a54 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c | |||
@@ -860,7 +860,7 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb) | |||
860 | /* Copy the data if there is no space for the header or if it's | 860 | /* Copy the data if there is no space for the header or if it's |
861 | * read-only. | 861 | * read-only. |
862 | */ | 862 | */ |
863 | if (skb_cow(skb, sizeof(*ph) + dev->hard_header_len)) | 863 | if (skb_cow_head(skb, sizeof(*ph) + dev->hard_header_len)) |
864 | goto abort; | 864 | goto abort; |
865 | 865 | ||
866 | __skb_push(skb, sizeof(*ph)); | 866 | __skb_push(skb, sizeof(*ph)); |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 93c27f71122a..a656cecd373c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -1352,6 +1352,22 @@ static inline int skb_clone_writable(struct sk_buff *skb, int len) | |||
1352 | skb_headroom(skb) + len <= skb->hdr_len; | 1352 | skb_headroom(skb) + len <= skb->hdr_len; |
1353 | } | 1353 | } |
1354 | 1354 | ||
1355 | static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom, | ||
1356 | int cloned) | ||
1357 | { | ||
1358 | int delta = 0; | ||
1359 | |||
1360 | if (headroom < NET_SKB_PAD) | ||
1361 | headroom = NET_SKB_PAD; | ||
1362 | if (headroom > skb_headroom(skb)) | ||
1363 | delta = headroom - skb_headroom(skb); | ||
1364 | |||
1365 | if (delta || cloned) | ||
1366 | return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0, | ||
1367 | GFP_ATOMIC); | ||
1368 | return 0; | ||
1369 | } | ||
1370 | |||
1355 | /** | 1371 | /** |
1356 | * skb_cow - copy header of skb when it is required | 1372 | * skb_cow - copy header of skb when it is required |
1357 | * @skb: buffer to cow | 1373 | * @skb: buffer to cow |
@@ -1366,16 +1382,22 @@ static inline int skb_clone_writable(struct sk_buff *skb, int len) | |||
1366 | */ | 1382 | */ |
1367 | static inline int skb_cow(struct sk_buff *skb, unsigned int headroom) | 1383 | static inline int skb_cow(struct sk_buff *skb, unsigned int headroom) |
1368 | { | 1384 | { |
1369 | int delta = (headroom > NET_SKB_PAD ? headroom : NET_SKB_PAD) - | 1385 | return __skb_cow(skb, headroom, skb_cloned(skb)); |
1370 | skb_headroom(skb); | 1386 | } |
1371 | |||
1372 | if (delta < 0) | ||
1373 | delta = 0; | ||
1374 | 1387 | ||
1375 | if (delta || skb_cloned(skb)) | 1388 | /** |
1376 | return pskb_expand_head(skb, (delta + (NET_SKB_PAD-1)) & | 1389 | * skb_cow_head - skb_cow but only making the head writable |
1377 | ~(NET_SKB_PAD-1), 0, GFP_ATOMIC); | 1390 | * @skb: buffer to cow |
1378 | return 0; | 1391 | * @headroom: needed headroom |
1392 | * | ||
1393 | * This function is identical to skb_cow except that we replace the | ||
1394 | * skb_cloned check by skb_header_cloned. It should be used when | ||
1395 | * you only need to push on some header and do not need to modify | ||
1396 | * the data. | ||
1397 | */ | ||
1398 | static inline int skb_cow_head(struct sk_buff *skb, unsigned int headroom) | ||
1399 | { | ||
1400 | return __skb_cow(skb, headroom, skb_header_cloned(skb)); | ||
1379 | } | 1401 | } |
1380 | 1402 | ||
1381 | /** | 1403 | /** |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 3ee2022928e3..fc13130035e7 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -183,7 +183,7 @@ int nf_bridge_copy_header(struct sk_buff *skb) | |||
183 | int err; | 183 | int err; |
184 | int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); | 184 | int header_size = ETH_HLEN + nf_bridge_encap_header_len(skb); |
185 | 185 | ||
186 | err = skb_cow(skb, header_size); | 186 | err = skb_cow_head(skb, header_size); |
187 | if (err) | 187 | if (err) |
188 | return err; | 188 | return err; |
189 | 189 | ||