usb: gadget: f_phonet: fix skb frags[] overflow in pn_rx_complete()
Greg Kroah-Hartman
maintainerPATCH 1/1 usb: gadget: f_phonet: fix skb frags[] overflow in pn_rx_complete()
A broken/bored/mean USB host can overflow the skb_shared_info->frags[] array on a Linux gadget exposing a Phonet function by sending an unbounded sequence of full-page OUT transfers.
pn_rx_complete() finalizes the skb only when req->actual < req->length, where req->length is set to PAGE_SIZE by the gadget. If the host always sends exactly PAGE_SIZE bytes per transfer, fp->rx.skb will never be reset and each completion will add another fragment via skb_add_rx_frag(). Once nr_frags exceeds MAX_SKB_FRAGS (default 17), subsequent frag stores overwrite memory adjacent to the shinfo on the heap.
Drop the skb and account a length error when the frag limit is reached, matching the fix applied in t7xx by commit f0813bcd2d9d ("net: wwan:
t7xx: fix potential skb->frags overflow in RX path").
--- drivers/usb/gadget/function/f_phonet.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/usb/gadget/function/f_phonet.c +9 -0
@@ -333,6 +333,15 @@ static void pn_rx_complete(struct usb_ep *ep, struct usb_request *req)if (unlikely (!skb))break ; +if (unlikely (skb_shinfo (skb)->nr_frags >=MAX_SKB_FRAGS )) { +/* Frame count from host exceeds frags[] capacity */ +dev_kfree_skb_any (skb); +if (fp->rx.skb == skb) + fp->rx.skb =NULL ; + dev->stats.rx_length_errors++; +break ; + } +if (skb->len ==0 ) {/* First fragment */ skb->protocol =htons (ETH_P_PHONET );skb_reset_mac_header (skb);
Signature · 1 line
2.53.0