Skip to content

Commit b6a7920

Browse files
sladkanidavem330
authored andcommitted
net: skbuff: Limit skb_vlan_pop/push() to expect skb->data at mac header
skb_vlan_pop/push were too generic, trying to support the cases where skb->data is at mac header, and cases where skb->data is arbitrarily elsewhere. Supporting an arbitrary skb->data was complex and bogus: - It failed to unwind skb->data to its original location post actual pop/push. (Also, semantic is not well defined for unwinding: If data was into the eth header, need to use same offset from start; But if data was at network header or beyond, need to adjust the original offset according to the push/pull) - It mangled the rcsum post actual push/pop, without taking into account that the eth bytes might already have been pulled out of the csum. Most callers (ovs, bpf) already had their skb->data at mac_header upon invoking skb_vlan_pop/push. Last caller that failed to do so (act_vlan) has been recently fixed. Therefore, to simplify things, no longer support arbitrary skb->data inputs for skb_vlan_pop/push(). skb->data is expected to be exactly at mac_header; WARN otherwise. Signed-off-by: Shmulik Ladkani <[email protected]> Cc: Daniel Borkmann <[email protected]> Cc: Pravin Shelar <[email protected]> Cc: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent f39acc8 commit b6a7920

File tree

1 file changed

+22
-15
lines changed

1 file changed

+22
-15
lines changed

net/core/skbuff.c

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4528,13 +4528,18 @@ EXPORT_SYMBOL(skb_ensure_writable);
45284528
int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci)
45294529
{
45304530
struct vlan_hdr *vhdr;
4531-
unsigned int offset = skb->data - skb_mac_header(skb);
4531+
int offset = skb->data - skb_mac_header(skb);
45324532
int err;
45334533

4534-
__skb_push(skb, offset);
4534+
if (WARN_ONCE(offset,
4535+
"__skb_vlan_pop got skb with skb->data not at mac header (offset %d)\n",
4536+
offset)) {
4537+
return -EINVAL;
4538+
}
4539+
45354540
err = skb_ensure_writable(skb, VLAN_ETH_HLEN);
45364541
if (unlikely(err))
4537-
goto pull;
4542+
return err;
45384543

45394544
skb_postpull_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
45404545

@@ -4551,13 +4556,14 @@ int __skb_vlan_pop(struct sk_buff *skb, u16 *vlan_tci)
45514556
skb_set_network_header(skb, ETH_HLEN);
45524557

45534558
skb_reset_mac_len(skb);
4554-
pull:
4555-
__skb_pull(skb, offset);
45564559

45574560
return err;
45584561
}
45594562
EXPORT_SYMBOL(__skb_vlan_pop);
45604563

4564+
/* Pop a vlan tag either from hwaccel or from payload.
4565+
* Expects skb->data at mac header.
4566+
*/
45614567
int skb_vlan_pop(struct sk_buff *skb)
45624568
{
45634569
u16 vlan_tci;
@@ -4588,29 +4594,30 @@ int skb_vlan_pop(struct sk_buff *skb)
45884594
}
45894595
EXPORT_SYMBOL(skb_vlan_pop);
45904596

4597+
/* Push a vlan tag either into hwaccel or into payload (if hwaccel tag present).
4598+
* Expects skb->data at mac header.
4599+
*/
45914600
int skb_vlan_push(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
45924601
{
45934602
if (skb_vlan_tag_present(skb)) {
4594-
unsigned int offset = skb->data - skb_mac_header(skb);
4603+
int offset = skb->data - skb_mac_header(skb);
45954604
int err;
45964605

4597-
/* __vlan_insert_tag expect skb->data pointing to mac header.
4598-
* So change skb->data before calling it and change back to
4599-
* original position later
4600-
*/
4601-
__skb_push(skb, offset);
4606+
if (WARN_ONCE(offset,
4607+
"skb_vlan_push got skb with skb->data not at mac header (offset %d)\n",
4608+
offset)) {
4609+
return -EINVAL;
4610+
}
4611+
46024612
err = __vlan_insert_tag(skb, skb->vlan_proto,
46034613
skb_vlan_tag_get(skb));
4604-
if (err) {
4605-
__skb_pull(skb, offset);
4614+
if (err)
46064615
return err;
4607-
}
46084616

46094617
skb->protocol = skb->vlan_proto;
46104618
skb->mac_len += VLAN_HLEN;
46114619

46124620
skb_postpush_rcsum(skb, skb->data + (2 * ETH_ALEN), VLAN_HLEN);
4613-
__skb_pull(skb, offset);
46144621
}
46154622
__vlan_hwaccel_put_tag(skb, vlan_proto, vlan_tci);
46164623
return 0;

0 commit comments

Comments
 (0)