@@ -37,6 +37,8 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
3737 struct ethhdr * eth_hdr ;
3838 struct hsr_sup_tag * hsr_sup_tag ;
3939 struct hsrv1_ethhdr_sp * hsr_V1_hdr ;
40+ struct hsr_sup_tlv * hsr_sup_tlv ;
41+ u16 total_length = 0 ;
4042
4143 WARN_ON_ONCE (!skb_mac_header_was_set (skb ));
4244 eth_hdr = (struct ethhdr * )skb_mac_header (skb );
@@ -53,23 +55,63 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
5355
5456 /* Get the supervision header from correct location. */
5557 if (eth_hdr -> h_proto == htons (ETH_P_HSR )) { /* Okay HSRv1. */
58+ total_length = sizeof (struct hsrv1_ethhdr_sp );
59+ if (!pskb_may_pull (skb , total_length ))
60+ return false;
61+
5662 hsr_V1_hdr = (struct hsrv1_ethhdr_sp * )skb_mac_header (skb );
5763 if (hsr_V1_hdr -> hsr .encap_proto != htons (ETH_P_PRP ))
5864 return false;
5965
6066 hsr_sup_tag = & hsr_V1_hdr -> hsr_sup ;
6167 } else {
68+ total_length = sizeof (struct hsrv0_ethhdr_sp );
69+ if (!pskb_may_pull (skb , total_length ))
70+ return false;
71+
6272 hsr_sup_tag =
6373 & ((struct hsrv0_ethhdr_sp * )skb_mac_header (skb ))-> hsr_sup ;
6474 }
6575
66- if (hsr_sup_tag -> HSR_TLV_type != HSR_TLV_ANNOUNCE &&
67- hsr_sup_tag -> HSR_TLV_type != HSR_TLV_LIFE_CHECK &&
68- hsr_sup_tag -> HSR_TLV_type != PRP_TLV_LIFE_CHECK_DD &&
69- hsr_sup_tag -> HSR_TLV_type != PRP_TLV_LIFE_CHECK_DA )
76+ if (hsr_sup_tag -> tlv .HSR_TLV_type != HSR_TLV_ANNOUNCE &&
77+ hsr_sup_tag -> tlv .HSR_TLV_type != HSR_TLV_LIFE_CHECK &&
78+ hsr_sup_tag -> tlv .HSR_TLV_type != PRP_TLV_LIFE_CHECK_DD &&
79+ hsr_sup_tag -> tlv .HSR_TLV_type != PRP_TLV_LIFE_CHECK_DA )
80+ return false;
81+ if (hsr_sup_tag -> tlv .HSR_TLV_length != 12 &&
82+ hsr_sup_tag -> tlv .HSR_TLV_length != sizeof (struct hsr_sup_payload ))
7083 return false;
71- if (hsr_sup_tag -> HSR_TLV_length != 12 &&
72- hsr_sup_tag -> HSR_TLV_length != sizeof (struct hsr_sup_payload ))
84+
85+ /* Get next tlv */
86+ total_length += sizeof (struct hsr_sup_tlv ) + hsr_sup_tag -> tlv .HSR_TLV_length ;
87+ if (!pskb_may_pull (skb , total_length ))
88+ return false;
89+ skb_pull (skb , total_length );
90+ hsr_sup_tlv = (struct hsr_sup_tlv * )skb -> data ;
91+ skb_push (skb , total_length );
92+
93+ /* if this is a redbox supervision frame we need to verify
94+ * that more data is available
95+ */
96+ if (hsr_sup_tlv -> HSR_TLV_type == PRP_TLV_REDBOX_MAC ) {
97+ /* tlv length must be a length of a mac address */
98+ if (hsr_sup_tlv -> HSR_TLV_length != sizeof (struct hsr_sup_payload ))
99+ return false;
100+
101+ /* make sure another tlv follows */
102+ total_length += sizeof (struct hsr_sup_tlv ) + hsr_sup_tlv -> HSR_TLV_length ;
103+ if (!pskb_may_pull (skb , total_length ))
104+ return false;
105+
106+ /* get next tlv */
107+ skb_pull (skb , total_length );
108+ hsr_sup_tlv = (struct hsr_sup_tlv * )skb -> data ;
109+ skb_push (skb , total_length );
110+ }
111+
112+ /* end of tlvs must follow at the end */
113+ if (hsr_sup_tlv -> HSR_TLV_type == HSR_TLV_EOT &&
114+ hsr_sup_tlv -> HSR_TLV_length != 0 )
73115 return false;
74116
75117 return true;
@@ -108,15 +150,15 @@ struct sk_buff *hsr_get_untagged_frame(struct hsr_frame_info *frame,
108150 struct hsr_port * port )
109151{
110152 if (!frame -> skb_std ) {
111- if (frame -> skb_hsr ) {
153+ if (frame -> skb_hsr )
112154 frame -> skb_std =
113155 create_stripped_skb_hsr (frame -> skb_hsr , frame );
114- } else {
115- /* Unexpected */
116- WARN_ONCE (1 , "%s:%d: Unexpected frame received (port_src %s)\n" ,
117- __FILE__ , __LINE__ , port -> dev -> name );
156+ else
157+ netdev_warn_once (port -> dev ,
158+ "Unexpected frame received in hsr_get_untagged_frame()\n" );
159+
160+ if (!frame -> skb_std )
118161 return NULL ;
119- }
120162 }
121163
122164 return skb_clone (frame -> skb_std , GFP_ATOMIC );
@@ -309,17 +351,18 @@ static void hsr_deliver_master(struct sk_buff *skb, struct net_device *dev,
309351 struct hsr_node * node_src )
310352{
311353 bool was_multicast_frame ;
312- int res ;
354+ int res , recv_len ;
313355
314356 was_multicast_frame = (skb -> pkt_type == PACKET_MULTICAST );
315357 hsr_addr_subst_source (node_src , skb );
316358 skb_pull (skb , ETH_HLEN );
359+ recv_len = skb -> len ;
317360 res = netif_rx (skb );
318361 if (res == NET_RX_DROP ) {
319362 dev -> stats .rx_dropped ++ ;
320363 } else {
321364 dev -> stats .rx_packets ++ ;
322- dev -> stats .rx_bytes += skb -> len ;
365+ dev -> stats .rx_bytes += recv_len ;
323366 if (was_multicast_frame )
324367 dev -> stats .multicast ++ ;
325368 }
@@ -457,7 +500,6 @@ static void handle_std_frame(struct sk_buff *skb,
457500{
458501 struct hsr_port * port = frame -> port_rcv ;
459502 struct hsr_priv * hsr = port -> hsr ;
460- unsigned long irqflags ;
461503
462504 frame -> skb_hsr = NULL ;
463505 frame -> skb_prp = NULL ;
@@ -467,10 +509,9 @@ static void handle_std_frame(struct sk_buff *skb,
467509 frame -> is_from_san = true;
468510 } else {
469511 /* Sequence nr for the master node */
470- spin_lock_irqsave (& hsr -> seqnr_lock , irqflags );
512+ lockdep_assert_held (& hsr -> seqnr_lock );
471513 frame -> sequence_nr = hsr -> sequence_nr ;
472514 hsr -> sequence_nr ++ ;
473- spin_unlock_irqrestore (& hsr -> seqnr_lock , irqflags );
474515 }
475516}
476517
@@ -571,11 +612,13 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port)
571612{
572613 struct hsr_frame_info frame ;
573614
615+ rcu_read_lock ();
574616 if (fill_frame_info (& frame , skb , port ) < 0 )
575617 goto out_drop ;
576618
577619 hsr_register_frame_in (frame .node_src , port , frame .sequence_nr );
578620 hsr_forward_do (& frame );
621+ rcu_read_unlock ();
579622 /* Gets called for ingress frames as well as egress from master port.
580623 * So check and increment stats for master port only here.
581624 */
@@ -590,6 +633,7 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port)
590633 return ;
591634
592635out_drop :
636+ rcu_read_unlock ();
593637 port -> dev -> stats .tx_dropped ++ ;
594638 kfree_skb (skb );
595639}
0 commit comments