]> git.hungrycats.org Git - linux/commitdiff
usb: dwc3: gadget: Fix looping of queued SG entries
authorThinh Nguyen <Thinh.Nguyen@synopsys.com>
Thu, 14 Nov 2024 01:02:18 +0000 (01:02 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Dec 2024 12:54:25 +0000 (13:54 +0100)
commit b7fc65f5141c24785dc8c19249ca4efcf71b3524 upstream.

The dwc3_request->num_queued_sgs is decremented on completion. If a
partially completed request is handled, then the
dwc3_request->num_queued_sgs no longer reflects the total number of
num_queued_sgs (it would be cleared).

Correctly check the number of request SG entries remained to be prepare
and queued. Failure to do this may cause null pointer dereference when
accessing non-existent SG entry.

Cc: stable@vger.kernel.org
Fixes: c96e6725db9d ("usb: dwc3: gadget: Correct the logic for queuing sgs")
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/d07a7c4aa0fcf746cdca0515150dbe5c52000af7.1731545781.git.Thinh.Nguyen@synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc3/gadget.c

index 881072cc3992bc25e5731e6751521aa47bfdb380..271f9dc9c035748930a2fa5d5eb382df2f1fd5a6 100644 (file)
@@ -1417,8 +1417,8 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
        struct scatterlist *s;
        int             i;
        unsigned int length = req->request.length;
-       unsigned int remaining = req->request.num_mapped_sgs
-               - req->num_queued_sgs;
+       unsigned int remaining = req->num_pending_sgs;
+       unsigned int num_queued_sgs = req->request.num_mapped_sgs - remaining;
        unsigned int num_trbs = req->num_trbs;
        bool needs_extra_trb = dwc3_needs_extra_trb(dep, req);
 
@@ -1426,7 +1426,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
         * If we resume preparing the request, then get the remaining length of
         * the request and resume where we left off.
         */
-       for_each_sg(req->request.sg, s, req->num_queued_sgs, i)
+       for_each_sg(req->request.sg, s, num_queued_sgs, i)
                length -= sg_dma_len(s);
 
        for_each_sg(sg, s, remaining, i) {