@@ -977,6 +977,8 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
977
977
struct usb_cdc_ncm_nth16 * nth16 ;
978
978
struct usb_cdc_ncm_ndp16 * ndp16 ;
979
979
struct usb_cdc_ncm_dpe16 * dpe16 ;
980
+ int ndpoffset ;
981
+ int loopcount = 50 ; /* arbitrary max preventing infinite loop */
980
982
981
983
if (ctx == NULL )
982
984
goto error ;
@@ -1010,41 +1012,40 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
1010
1012
}
1011
1013
ctx -> rx_seq = le16_to_cpu (nth16 -> wSequence );
1012
1014
1013
- len = le16_to_cpu (nth16 -> wNdpIndex );
1014
- if (( len + sizeof ( struct usb_cdc_ncm_ndp16 )) > skb_in -> len ) {
1015
- pr_debug ( "invalid DPT16 index <%u>\n" ,
1016
- le16_to_cpu ( nth16 -> wNdpIndex ) );
1015
+ ndpoffset = le16_to_cpu (nth16 -> wNdpIndex );
1016
+ next_ndp :
1017
+ if (( ndpoffset + sizeof ( struct usb_cdc_ncm_ndp16 )) > skb_in -> len ) {
1018
+ pr_debug ( "invalid NDP offset <%u>\n" , ndpoffset );
1017
1019
goto error ;
1018
1020
}
1019
-
1020
- ndp16 = (struct usb_cdc_ncm_ndp16 * )(((u8 * )skb_in -> data ) + len );
1021
+ ndp16 = (struct usb_cdc_ncm_ndp16 * )(skb_in -> data + ndpoffset );
1021
1022
1022
1023
if (le32_to_cpu (ndp16 -> dwSignature ) != USB_CDC_NCM_NDP16_NOCRC_SIGN ) {
1023
1024
pr_debug ("invalid DPT16 signature <%u>\n" ,
1024
1025
le32_to_cpu (ndp16 -> dwSignature ));
1025
- goto error ;
1026
+ goto err_ndp ;
1026
1027
}
1027
1028
1028
1029
if (le16_to_cpu (ndp16 -> wLength ) < USB_CDC_NCM_NDP16_LENGTH_MIN ) {
1029
1030
pr_debug ("invalid DPT16 length <%u>\n" ,
1030
1031
le32_to_cpu (ndp16 -> dwSignature ));
1031
- goto error ;
1032
+ goto err_ndp ;
1032
1033
}
1033
1034
1034
1035
nframes = ((le16_to_cpu (ndp16 -> wLength ) -
1035
1036
sizeof (struct usb_cdc_ncm_ndp16 )) /
1036
1037
sizeof (struct usb_cdc_ncm_dpe16 ));
1037
1038
nframes -- ; /* we process NDP entries except for the last one */
1038
1039
1039
- len += sizeof (struct usb_cdc_ncm_ndp16 );
1040
+ ndpoffset += sizeof (struct usb_cdc_ncm_ndp16 );
1040
1041
1041
- if ((len + nframes * (sizeof (struct usb_cdc_ncm_dpe16 ))) >
1042
+ if ((ndpoffset + nframes * (sizeof (struct usb_cdc_ncm_dpe16 ))) >
1042
1043
skb_in -> len ) {
1043
1044
pr_debug ("Invalid nframes = %d\n" , nframes );
1044
- goto error ;
1045
+ goto err_ndp ;
1045
1046
}
1046
1047
1047
- dpe16 = (struct usb_cdc_ncm_dpe16 * )((( u8 * ) skb_in -> data ) + len );
1048
+ dpe16 = (struct usb_cdc_ncm_dpe16 * )(skb_in -> data + ndpoffset );
1048
1049
1049
1050
for (x = 0 ; x < nframes ; x ++ , dpe16 ++ ) {
1050
1051
offset = le16_to_cpu (dpe16 -> wDatagramIndex );
@@ -1056,7 +1057,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
1056
1057
*/
1057
1058
if ((offset == 0 ) || (len == 0 )) {
1058
1059
if (!x )
1059
- goto error ; /* empty NTB */
1060
+ goto err_ndp ; /* empty NTB */
1060
1061
break ;
1061
1062
}
1062
1063
@@ -1067,7 +1068,7 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
1067
1068
"offset[%u]=%u, length=%u, skb=%p\n" ,
1068
1069
x , offset , len , skb_in );
1069
1070
if (!x )
1070
- goto error ;
1071
+ goto err_ndp ;
1071
1072
break ;
1072
1073
1073
1074
} else {
@@ -1080,6 +1081,12 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
1080
1081
usbnet_skb_return (dev , skb );
1081
1082
}
1082
1083
}
1084
+ err_ndp :
1085
+ /* are there more NDPs to process? */
1086
+ ndpoffset = le16_to_cpu (ndp16 -> wNextNdpIndex );
1087
+ if (ndpoffset && loopcount -- )
1088
+ goto next_ndp ;
1089
+
1083
1090
return 1 ;
1084
1091
error :
1085
1092
return 0 ;
0 commit comments