Skip to content

Commit d549699

Browse files
ebirgerkuba-moo
authored andcommitted
net/packet: fix packet receive on L3 devices without visible hard header
In the patchset merged by commit b9fcf0a ("Merge branch 'support-AF_PACKET-for-layer-3-devices'") L3 devices which did not have header_ops were given one for the purpose of protocol parsing on af_packet transmit path. That change made af_packet receive path regard these devices as having a visible L3 header and therefore aligned incoming skb->data to point to the skb's mac_header. Some devices, such as ipip, xfrmi, and others, do not reset their mac_header prior to ingress and therefore their incoming packets became malformed. Ideally these devices would reset their mac headers, or af_packet would be able to rely on dev->hard_header_len being 0 for such cases, but it seems this is not the case. Fix by changing af_packet RX ll visibility criteria to include the existence of a '.create()' header operation, which is used when creating a device hard header - via dev_hard_header() - by upper layers, and does not exist in these L3 devices. As this predicate may be useful in other situations, add it as a common dev_has_header() helper in netdevice.h. Fixes: b9fcf0a ("Merge branch 'support-AF_PACKET-for-layer-3-devices'") Signed-off-by: Eyal Birger <[email protected]> Acked-by: Jason A. Donenfeld <[email protected]> Acked-by: Willem de Bruijn <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent 2980cbd commit d549699

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

include/linux/netdevice.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3137,6 +3137,11 @@ static inline bool dev_validate_header(const struct net_device *dev,
31373137
return false;
31383138
}
31393139

3140+
static inline bool dev_has_header(const struct net_device *dev)
3141+
{
3142+
return dev->header_ops && dev->header_ops->create;
3143+
}
3144+
31403145
typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr,
31413146
int len, int size);
31423147
int register_gifconf(unsigned int family, gifconf_func_t *gifconf);

net/packet/af_packet.c

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@
9393

9494
/*
9595
Assumptions:
96-
- If the device has no dev->header_ops, there is no LL header visible
97-
above the device. In this case, its hard_header_len should be 0.
96+
- If the device has no dev->header_ops->create, there is no LL header
97+
visible above the device. In this case, its hard_header_len should be 0.
9898
The device may prepend its own header internally. In this case, its
9999
needed_headroom should be set to the space needed for it to add its
100100
internal header.
@@ -108,26 +108,26 @@
108108
On receive:
109109
-----------
110110
111-
Incoming, dev->header_ops != NULL
111+
Incoming, dev_has_header(dev) == true
112112
mac_header -> ll header
113113
data -> data
114114
115-
Outgoing, dev->header_ops != NULL
115+
Outgoing, dev_has_header(dev) == true
116116
mac_header -> ll header
117117
data -> ll header
118118
119-
Incoming, dev->header_ops == NULL
119+
Incoming, dev_has_header(dev) == false
120120
mac_header -> data
121121
However drivers often make it point to the ll header.
122122
This is incorrect because the ll header should be invisible to us.
123123
data -> data
124124
125-
Outgoing, dev->header_ops == NULL
125+
Outgoing, dev_has_header(dev) == false
126126
mac_header -> data. ll header is invisible to us.
127127
data -> data
128128
129129
Resume
130-
If dev->header_ops == NULL we are unable to restore the ll header,
130+
If dev_has_header(dev) == false we are unable to restore the ll header,
131131
because it is invisible to us.
132132
133133
@@ -2069,7 +2069,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev,
20692069

20702070
skb->dev = dev;
20712071

2072-
if (dev->header_ops) {
2072+
if (dev_has_header(dev)) {
20732073
/* The device has an explicit notion of ll header,
20742074
* exported to higher levels.
20752075
*
@@ -2198,7 +2198,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
21982198
if (!net_eq(dev_net(dev), sock_net(sk)))
21992199
goto drop;
22002200

2201-
if (dev->header_ops) {
2201+
if (dev_has_header(dev)) {
22022202
if (sk->sk_type != SOCK_DGRAM)
22032203
skb_push(skb, skb->data - skb_mac_header(skb));
22042204
else if (skb->pkt_type == PACKET_OUTGOING) {

0 commit comments

Comments
 (0)