Re: [PATCH v4] usb: gadget: ncm: Handle decoding of multiple NTB's in unwrap call

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Sep 27, 2023 at 3:59 AM Krishna Kurapati
<quic_kriskura@xxxxxxxxxxx> wrote:
>
> When NCM is used with hosts like Windows PC, it is observed that there are
> multiple NTB's contained in one usb request giveback. Since the driver
> unwraps the obtained request data assuming only one NTB is present, we
> loose the subsequent NTB's present resulting in data loss.
>
> Fix this by checking the parsed block length with the obtained data
> length in usb request and continue parsing after the last byte of current
> NTB.
>
> Cc: stable@xxxxxxxxxxxxxxx
> Fixes: 9f6ce4240a2b ("usb: gadget: f_ncm.c added")
> Signed-off-by: Krishna Kurapati <quic_kriskura@xxxxxxxxxxx>
> ---
> Changes in v4: Replaced void* with __le16* typecast for tmp variable
> Changes in v3: Removed explicit void* typecast for ntb_ptr variable
>
>  drivers/usb/gadget/function/f_ncm.c | 26 +++++++++++++++++++-------
>  1 file changed, 19 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/usb/gadget/function/f_ncm.c b/drivers/usb/gadget/function/f_ncm.c
> index 424bb3b666db..faf90a217419 100644
> --- a/drivers/usb/gadget/function/f_ncm.c
> +++ b/drivers/usb/gadget/function/f_ncm.c
> @@ -1171,7 +1171,8 @@ static int ncm_unwrap_ntb(struct gether *port,
>                           struct sk_buff_head *list)
>  {
>         struct f_ncm    *ncm = func_to_ncm(&port->func);
> -       __le16          *tmp = (void *) skb->data;
> +       unsigned char   *ntb_ptr = skb->data;
> +       __le16          *tmp;
>         unsigned        index, index2;
>         int             ndp_index;
>         unsigned        dg_len, dg_len2;
> @@ -1184,6 +1185,10 @@ static int ncm_unwrap_ntb(struct gether *port,
>         const struct ndp_parser_opts *opts = ncm->parser_opts;
>         unsigned        crc_len = ncm->is_crc ? sizeof(uint32_t) : 0;
>         int             dgram_counter;
> +       int             to_process = skb->len;
> +
> +parse_ntb:
> +       tmp = (__le16 *)ntb_ptr;
>
>         /* dwSignature */
>         if (get_unaligned_le32(tmp) != opts->nth_sign) {
> @@ -1230,7 +1235,7 @@ static int ncm_unwrap_ntb(struct gether *port,
>                  * walk through NDP
>                  * dwSignature
>                  */
> -               tmp = (void *)(skb->data + ndp_index);
> +               tmp = (__le16 *)(ntb_ptr + ndp_index);
>                 if (get_unaligned_le32(tmp) != ncm->ndp_sign) {
>                         INFO(port->func.config->cdev, "Wrong NDP SIGN\n");
>                         goto err;
> @@ -1287,11 +1292,11 @@ static int ncm_unwrap_ntb(struct gether *port,
>                         if (ncm->is_crc) {
>                                 uint32_t crc, crc2;
>
> -                               crc = get_unaligned_le32(skb->data +
> +                               crc = get_unaligned_le32(ntb_ptr +
>                                                          index + dg_len -
>                                                          crc_len);
>                                 crc2 = ~crc32_le(~0,
> -                                                skb->data + index,
> +                                                ntb_ptr + index,
>                                                  dg_len - crc_len);
>                                 if (crc != crc2) {
>                                         INFO(port->func.config->cdev,
> @@ -1318,7 +1323,7 @@ static int ncm_unwrap_ntb(struct gether *port,
>                                                          dg_len - crc_len);
>                         if (skb2 == NULL)
>                                 goto err;
> -                       skb_put_data(skb2, skb->data + index,
> +                       skb_put_data(skb2, ntb_ptr + index,
>                                      dg_len - crc_len);
>
>                         skb_queue_tail(list, skb2);
> @@ -1331,10 +1336,17 @@ static int ncm_unwrap_ntb(struct gether *port,
>                 } while (ndp_len > 2 * (opts->dgram_item_len * 2));
>         } while (ndp_index);
>
> -       dev_consume_skb_any(skb);
> -
>         VDBG(port->func.config->cdev,
>              "Parsed NTB with %d frames\n", dgram_counter);
> +
> +       to_process -= block_len;
> +       if (to_process != 0) {
> +               ntb_ptr = (unsigned char *)(ntb_ptr + block_len);
> +               goto parse_ntb;
> +       }
> +
> +       dev_consume_skb_any(skb);
> +
>         return 0;
>  err:
>         skb_queue_purge(list);
> --
> 2.42.0

Reviewed-by: Maciej Żenczykowski <maze@xxxxxxxxxx>





[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux