Skip to content

Commit ff06ab1

Browse files
bmorkdavem330
authored andcommitted
net: cdc_ncm: splitting rx_fixup for code reuse
Verifying and handling received MBIM and NCM frames will need to be different in three areas: - verifying the NDP signature - checking valid datagram length - datagram header manipulation This makes it inconvenient to share rx_fixup in whole. But some verification parts are common. Split these out in separate functions. Signed-off-by: Bjørn Mork <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 75d67d3 commit ff06ab1

File tree

1 file changed

+55
-28
lines changed

1 file changed

+55
-28
lines changed

drivers/net/usb/cdc_ncm.c

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -966,19 +966,12 @@ cdc_ncm_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
966966
return NULL;
967967
}
968968

969-
static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
969+
/* verify NTB header and return offset of first NDP, or negative error */
970+
static int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
970971
{
971-
struct sk_buff *skb;
972-
struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
973-
int len;
974-
int nframes;
975-
int x;
976-
int offset;
977972
struct usb_cdc_ncm_nth16 *nth16;
978-
struct usb_cdc_ncm_ndp16 *ndp16;
979-
struct usb_cdc_ncm_dpe16 *dpe16;
980-
int ndpoffset;
981-
int loopcount = 50; /* arbitrary max preventing infinite loop */
973+
int len;
974+
int ret = -EINVAL;
982975

983976
if (ctx == NULL)
984977
goto error;
@@ -1012,40 +1005,74 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
10121005
}
10131006
ctx->rx_seq = le16_to_cpu(nth16->wSequence);
10141007

1015-
ndpoffset = le16_to_cpu(nth16->wNdpIndex);
1016-
next_ndp:
1008+
ret = le16_to_cpu(nth16->wNdpIndex);
1009+
error:
1010+
return ret;
1011+
}
1012+
1013+
/* verify NDP header and return number of datagrams, or negative error */
1014+
static int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
1015+
{
1016+
struct usb_cdc_ncm_ndp16 *ndp16;
1017+
int ret = -EINVAL;
1018+
10171019
if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
10181020
pr_debug("invalid NDP offset <%u>\n", ndpoffset);
10191021
goto error;
10201022
}
10211023
ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
10221024

1023-
if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
1024-
pr_debug("invalid DPT16 signature <%u>\n",
1025-
le32_to_cpu(ndp16->dwSignature));
1026-
goto err_ndp;
1027-
}
1028-
10291025
if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
10301026
pr_debug("invalid DPT16 length <%u>\n",
10311027
le32_to_cpu(ndp16->dwSignature));
1032-
goto err_ndp;
1028+
goto error;
10331029
}
10341030

1035-
nframes = ((le16_to_cpu(ndp16->wLength) -
1031+
ret = ((le16_to_cpu(ndp16->wLength) -
10361032
sizeof(struct usb_cdc_ncm_ndp16)) /
10371033
sizeof(struct usb_cdc_ncm_dpe16));
1038-
nframes--; /* we process NDP entries except for the last one */
1039-
1040-
ndpoffset += sizeof(struct usb_cdc_ncm_ndp16);
1034+
ret--; /* we process NDP entries except for the last one */
10411035

1042-
if ((ndpoffset + nframes * (sizeof(struct usb_cdc_ncm_dpe16))) >
1036+
if ((sizeof(struct usb_cdc_ncm_ndp16) + ret * (sizeof(struct usb_cdc_ncm_dpe16))) >
10431037
skb_in->len) {
1044-
pr_debug("Invalid nframes = %d\n", nframes);
1045-
goto err_ndp;
1038+
pr_debug("Invalid nframes = %d\n", ret);
1039+
ret = -EINVAL;
10461040
}
10471041

1048-
dpe16 = (struct usb_cdc_ncm_dpe16 *)(skb_in->data + ndpoffset);
1042+
error:
1043+
return ret;
1044+
}
1045+
1046+
static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
1047+
{
1048+
struct sk_buff *skb;
1049+
struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
1050+
int len;
1051+
int nframes;
1052+
int x;
1053+
int offset;
1054+
struct usb_cdc_ncm_ndp16 *ndp16;
1055+
struct usb_cdc_ncm_dpe16 *dpe16;
1056+
int ndpoffset;
1057+
int loopcount = 50; /* arbitrary max preventing infinite loop */
1058+
1059+
ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
1060+
if (ndpoffset < 0)
1061+
goto error;
1062+
1063+
next_ndp:
1064+
nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
1065+
if (nframes < 0)
1066+
goto error;
1067+
1068+
ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
1069+
1070+
if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
1071+
pr_debug("invalid DPT16 signature <%u>\n",
1072+
le32_to_cpu(ndp16->dwSignature));
1073+
goto err_ndp;
1074+
}
1075+
dpe16 = ndp16->dpe16;
10491076

10501077
for (x = 0; x < nframes; x++, dpe16++) {
10511078
offset = le16_to_cpu(dpe16->wDatagramIndex);

0 commit comments

Comments
 (0)