mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-10 07:00:48 +00:00
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 <bjorn@mork.no> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
75d67d354f
commit
ff06ab13a4
@ -966,19 +966,12 @@ error:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
|
/* verify NTB header and return offset of first NDP, or negative error */
|
||||||
|
static int cdc_ncm_rx_verify_nth16(struct cdc_ncm_ctx *ctx, struct sk_buff *skb_in)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
|
||||||
struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
|
|
||||||
int len;
|
|
||||||
int nframes;
|
|
||||||
int x;
|
|
||||||
int offset;
|
|
||||||
struct usb_cdc_ncm_nth16 *nth16;
|
struct usb_cdc_ncm_nth16 *nth16;
|
||||||
struct usb_cdc_ncm_ndp16 *ndp16;
|
int len;
|
||||||
struct usb_cdc_ncm_dpe16 *dpe16;
|
int ret = -EINVAL;
|
||||||
int ndpoffset;
|
|
||||||
int loopcount = 50; /* arbitrary max preventing infinite loop */
|
|
||||||
|
|
||||||
if (ctx == NULL)
|
if (ctx == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
@ -1012,40 +1005,74 @@ static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
|
|||||||
}
|
}
|
||||||
ctx->rx_seq = le16_to_cpu(nth16->wSequence);
|
ctx->rx_seq = le16_to_cpu(nth16->wSequence);
|
||||||
|
|
||||||
ndpoffset = le16_to_cpu(nth16->wNdpIndex);
|
ret = le16_to_cpu(nth16->wNdpIndex);
|
||||||
next_ndp:
|
error:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* verify NDP header and return number of datagrams, or negative error */
|
||||||
|
static int cdc_ncm_rx_verify_ndp16(struct sk_buff *skb_in, int ndpoffset)
|
||||||
|
{
|
||||||
|
struct usb_cdc_ncm_ndp16 *ndp16;
|
||||||
|
int ret = -EINVAL;
|
||||||
|
|
||||||
if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
|
if ((ndpoffset + sizeof(struct usb_cdc_ncm_ndp16)) > skb_in->len) {
|
||||||
pr_debug("invalid NDP offset <%u>\n", ndpoffset);
|
pr_debug("invalid NDP offset <%u>\n", ndpoffset);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
|
ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
|
||||||
|
|
||||||
if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
|
|
||||||
pr_debug("invalid DPT16 signature <%u>\n",
|
|
||||||
le32_to_cpu(ndp16->dwSignature));
|
|
||||||
goto err_ndp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
|
if (le16_to_cpu(ndp16->wLength) < USB_CDC_NCM_NDP16_LENGTH_MIN) {
|
||||||
pr_debug("invalid DPT16 length <%u>\n",
|
pr_debug("invalid DPT16 length <%u>\n",
|
||||||
le32_to_cpu(ndp16->dwSignature));
|
le32_to_cpu(ndp16->dwSignature));
|
||||||
goto err_ndp;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
nframes = ((le16_to_cpu(ndp16->wLength) -
|
ret = ((le16_to_cpu(ndp16->wLength) -
|
||||||
sizeof(struct usb_cdc_ncm_ndp16)) /
|
sizeof(struct usb_cdc_ncm_ndp16)) /
|
||||||
sizeof(struct usb_cdc_ncm_dpe16));
|
sizeof(struct usb_cdc_ncm_dpe16));
|
||||||
nframes--; /* we process NDP entries except for the last one */
|
ret--; /* we process NDP entries except for the last one */
|
||||||
|
|
||||||
ndpoffset += sizeof(struct usb_cdc_ncm_ndp16);
|
if ((sizeof(struct usb_cdc_ncm_ndp16) + ret * (sizeof(struct usb_cdc_ncm_dpe16))) >
|
||||||
|
|
||||||
if ((ndpoffset + nframes * (sizeof(struct usb_cdc_ncm_dpe16))) >
|
|
||||||
skb_in->len) {
|
skb_in->len) {
|
||||||
pr_debug("Invalid nframes = %d\n", nframes);
|
pr_debug("Invalid nframes = %d\n", ret);
|
||||||
goto err_ndp;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
dpe16 = (struct usb_cdc_ncm_dpe16 *)(skb_in->data + ndpoffset);
|
error:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cdc_ncm_rx_fixup(struct usbnet *dev, struct sk_buff *skb_in)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
struct cdc_ncm_ctx *ctx = (struct cdc_ncm_ctx *)dev->data[0];
|
||||||
|
int len;
|
||||||
|
int nframes;
|
||||||
|
int x;
|
||||||
|
int offset;
|
||||||
|
struct usb_cdc_ncm_ndp16 *ndp16;
|
||||||
|
struct usb_cdc_ncm_dpe16 *dpe16;
|
||||||
|
int ndpoffset;
|
||||||
|
int loopcount = 50; /* arbitrary max preventing infinite loop */
|
||||||
|
|
||||||
|
ndpoffset = cdc_ncm_rx_verify_nth16(ctx, skb_in);
|
||||||
|
if (ndpoffset < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
next_ndp:
|
||||||
|
nframes = cdc_ncm_rx_verify_ndp16(skb_in, ndpoffset);
|
||||||
|
if (nframes < 0)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
ndp16 = (struct usb_cdc_ncm_ndp16 *)(skb_in->data + ndpoffset);
|
||||||
|
|
||||||
|
if (le32_to_cpu(ndp16->dwSignature) != USB_CDC_NCM_NDP16_NOCRC_SIGN) {
|
||||||
|
pr_debug("invalid DPT16 signature <%u>\n",
|
||||||
|
le32_to_cpu(ndp16->dwSignature));
|
||||||
|
goto err_ndp;
|
||||||
|
}
|
||||||
|
dpe16 = ndp16->dpe16;
|
||||||
|
|
||||||
for (x = 0; x < nframes; x++, dpe16++) {
|
for (x = 0; x < nframes; x++, dpe16++) {
|
||||||
offset = le16_to_cpu(dpe16->wDatagramIndex);
|
offset = le16_to_cpu(dpe16->wDatagramIndex);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user