Skip to content

Commit 48b491a

Browse files
gmccollisterdavem330
authored andcommitted
net: hsr: fix mac_len checks
Commit 2e9f609 ("net: hsr: check skb can contain struct hsr_ethhdr in fill_frame_info") added the following which resulted in -EINVAL always being returned: if (skb->mac_len < sizeof(struct hsr_ethhdr)) return -EINVAL; mac_len was not being set correctly so this check completely broke HSR/PRP since it was always 14, not 20. Set mac_len correctly and modify the mac_len checks to test in the correct places since sometimes it is legitimately 14. Fixes: 2e9f609 ("net: hsr: check skb can contain struct hsr_ethhdr in fill_frame_info") Signed-off-by: George McCollister <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a4dd4fc commit 48b491a

File tree

5 files changed

+34
-21
lines changed

5 files changed

+34
-21
lines changed

net/hsr/hsr_device.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
218218
if (master) {
219219
skb->dev = master->dev;
220220
skb_reset_mac_header(skb);
221+
skb_reset_mac_len(skb);
221222
hsr_forward_skb(skb, master);
222223
} else {
223224
atomic_long_inc(&dev->tx_dropped);
@@ -259,6 +260,7 @@ static struct sk_buff *hsr_init_skb(struct hsr_port *master)
259260
goto out;
260261

261262
skb_reset_mac_header(skb);
263+
skb_reset_mac_len(skb);
262264
skb_reset_network_header(skb);
263265
skb_reset_transport_header(skb);
264266

net/hsr/hsr_forward.c

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -474,29 +474,35 @@ static void handle_std_frame(struct sk_buff *skb,
474474
}
475475
}
476476

477-
void hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
478-
struct hsr_frame_info *frame)
477+
int hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
478+
struct hsr_frame_info *frame)
479479
{
480480
struct hsr_port *port = frame->port_rcv;
481481
struct hsr_priv *hsr = port->hsr;
482482

483483
/* HSRv0 supervisory frames double as a tag so treat them as tagged. */
484484
if ((!hsr->prot_version && proto == htons(ETH_P_PRP)) ||
485485
proto == htons(ETH_P_HSR)) {
486+
/* Check if skb contains hsr_ethhdr */
487+
if (skb->mac_len < sizeof(struct hsr_ethhdr))
488+
return -EINVAL;
489+
486490
/* HSR tagged frame :- Data or Supervision */
487491
frame->skb_std = NULL;
488492
frame->skb_prp = NULL;
489493
frame->skb_hsr = skb;
490494
frame->sequence_nr = hsr_get_skb_sequence_nr(skb);
491-
return;
495+
return 0;
492496
}
493497

494498
/* Standard frame or PRP from master port */
495499
handle_std_frame(skb, frame);
500+
501+
return 0;
496502
}
497503

498-
void prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
499-
struct hsr_frame_info *frame)
504+
int prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
505+
struct hsr_frame_info *frame)
500506
{
501507
/* Supervision frame */
502508
struct prp_rct *rct = skb_get_PRP_rct(skb);
@@ -507,9 +513,11 @@ void prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
507513
frame->skb_std = NULL;
508514
frame->skb_prp = skb;
509515
frame->sequence_nr = prp_get_skb_sequence_nr(rct);
510-
return;
516+
return 0;
511517
}
512518
handle_std_frame(skb, frame);
519+
520+
return 0;
513521
}
514522

515523
static int fill_frame_info(struct hsr_frame_info *frame,
@@ -519,9 +527,10 @@ static int fill_frame_info(struct hsr_frame_info *frame,
519527
struct hsr_vlan_ethhdr *vlan_hdr;
520528
struct ethhdr *ethhdr;
521529
__be16 proto;
530+
int ret;
522531

523-
/* Check if skb contains hsr_ethhdr */
524-
if (skb->mac_len < sizeof(struct hsr_ethhdr))
532+
/* Check if skb contains ethhdr */
533+
if (skb->mac_len < sizeof(struct ethhdr))
525534
return -EINVAL;
526535

527536
memset(frame, 0, sizeof(*frame));
@@ -548,7 +557,10 @@ static int fill_frame_info(struct hsr_frame_info *frame,
548557

549558
frame->is_from_san = false;
550559
frame->port_rcv = port;
551-
hsr->proto_ops->fill_frame_info(proto, skb, frame);
560+
ret = hsr->proto_ops->fill_frame_info(proto, skb, frame);
561+
if (ret)
562+
return ret;
563+
552564
check_local_dest(port->hsr, skb, frame);
553565

554566
return 0;

net/hsr/hsr_forward.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ struct sk_buff *prp_get_untagged_frame(struct hsr_frame_info *frame,
2424
struct hsr_port *port);
2525
bool prp_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port);
2626
bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port);
27-
void prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
28-
struct hsr_frame_info *frame);
29-
void hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
30-
struct hsr_frame_info *frame);
27+
int prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
28+
struct hsr_frame_info *frame);
29+
int hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
30+
struct hsr_frame_info *frame);
3131
#endif /* __HSR_FORWARD_H */

net/hsr/hsr_main.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ struct hsr_proto_ops {
186186
struct hsr_port *port);
187187
struct sk_buff * (*create_tagged_frame)(struct hsr_frame_info *frame,
188188
struct hsr_port *port);
189-
void (*fill_frame_info)(__be16 proto, struct sk_buff *skb,
190-
struct hsr_frame_info *frame);
189+
int (*fill_frame_info)(__be16 proto, struct sk_buff *skb,
190+
struct hsr_frame_info *frame);
191191
bool (*invalid_dan_ingress_frame)(__be16 protocol);
192192
void (*update_san_info)(struct hsr_node *node, bool is_sup);
193193
};

net/hsr/hsr_slave.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,11 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
6060
goto finish_pass;
6161

6262
skb_push(skb, ETH_HLEN);
63-
64-
if (skb_mac_header(skb) != skb->data) {
65-
WARN_ONCE(1, "%s:%d: Malformed frame at source port %s)\n",
66-
__func__, __LINE__, port->dev->name);
67-
goto finish_consume;
68-
}
63+
skb_reset_mac_header(skb);
64+
if ((!hsr->prot_version && protocol == htons(ETH_P_PRP)) ||
65+
protocol == htons(ETH_P_HSR))
66+
skb_set_network_header(skb, ETH_HLEN + HSR_HLEN);
67+
skb_reset_mac_len(skb);
6968

7069
hsr_forward_skb(skb, port);
7170

0 commit comments

Comments
 (0)