All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg KH <gregkh@linuxfoundation.org>
To: Zixuan Fu <r33s3n6@gmail.com>
Cc: mathias.nyman@intel.com, linux-usb@vger.kernel.org,
	linux-kernel@vger.kernel.org, baijiaju1990@gmail.com,
	TOTE Robot <oslab@tsinghua.edu.cn>
Subject: Re: [PATCH] drivers: usb: host: fix NULL pointer dereferences triggered by unhandled errors in xhci_create_rhub_port_array()
Date: Thu, 21 Apr 2022 12:07:36 +0200	[thread overview]
Message-ID: <YmEs6BqcyM7fgLXg@kroah.com> (raw)
In-Reply-To: <20220421094236.1052170-1-r33s3n6@gmail.com>

On Thu, Apr 21, 2022 at 05:42:36PM +0800, Zixuan Fu wrote:
> In xhci_create_rhub_port_array(), when rhub->num_ports is zero, 
> rhub->ports would not be set; when kcalloc_node() fails, rhub->ports
> would be set to NULL. In these two cases, xhci_create_rhub_port_array()
> just returns void, and thus its callers are unaware of the error.
> 
> Then rhub->ports is dereferenced in xhci_usb3_hub_descriptor() or 
> xhci_usb2_hub_descriptor().
> 
> To fix the bug, xhci_setup_port_arrays() should return an integer to 
> indicate a possible error, and its callers should handle the error.
> 
> Here is the log when this bug occurred in our fault-injection testing:
> 
> [   24.001309] BUG: kernel NULL pointer dereference, address: 0000000000000000
> ...
> [   24.003992] RIP: 0010:xhci_hub_control+0x3f5/0x60d0 [xhci_hcd]
> ...
> [   24.009803] Call Trace:
> [   24.010014]  <TASK>
> [   24.011310]  usb_hcd_submit_urb+0x1233/0x1fd0
> [   24.017071]  usb_start_wait_urb+0x115/0x310
> [   24.017641]  usb_control_msg+0x28a/0x450
> [   24.019046]  hub_probe+0xb16/0x2320
> [   24.019757]  usb_probe_interface+0x4f1/0x930
> [   24.019765]  really_probe+0x33d/0x970
> [   24.019768]  __driver_probe_device+0x157/0x210
> [   24.019772]  driver_probe_device+0x4f/0x340
> [   24.019775]  __device_attach_driver+0x2ee/0x3a0
> ...
> 
> Reported-by: TOTE Robot <oslab@tsinghua.edu.cn>
> Signed-off-by: Zixuan Fu <r33s3n6@gmail.com>
> ---
>  drivers/usb/host/xhci-mem.c | 17 ++++++++++++-----
>  1 file changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
> index bbb27ee2c6a3..024515346c39 100644
> --- a/drivers/usb/host/xhci-mem.c
> +++ b/drivers/usb/host/xhci-mem.c
> @@ -2235,7 +2235,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
>  	/* FIXME: Should we disable ports not in the Extended Capabilities? */
>  }
>  
> -static void xhci_create_rhub_port_array(struct xhci_hcd *xhci,
> +static int xhci_create_rhub_port_array(struct xhci_hcd *xhci,
>  					struct xhci_hub *rhub, gfp_t flags)
>  {
>  	int port_index = 0;
> @@ -2243,11 +2243,11 @@ static void xhci_create_rhub_port_array(struct xhci_hcd *xhci,
>  	struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
>  
>  	if (!rhub->num_ports)
> -		return;
> +		return -EINVAL;
>  	rhub->ports = kcalloc_node(rhub->num_ports, sizeof(*rhub->ports),
>  			flags, dev_to_node(dev));
>  	if (!rhub->ports)
> -		return;
> +		return -ENOMEM;
>  
>  	for (i = 0; i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
>  		if (xhci->hw_ports[i].rhub != rhub ||
> @@ -2259,6 +2259,7 @@ static void xhci_create_rhub_port_array(struct xhci_hcd *xhci,
>  		if (port_index == rhub->num_ports)
>  			break;
>  	}
> +	return 0;
>  }
>  
>  /*
> @@ -2277,6 +2278,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
>  	int cap_count = 0;
>  	u32 cap_start;
>  	struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
> +	int ret;
>  
>  	num_ports = HCS_MAX_PORTS(xhci->hcs_params1);
>  	xhci->hw_ports = kcalloc_node(num_ports, sizeof(*xhci->hw_ports),
> @@ -2367,8 +2369,13 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
>  	 * Not sure how the USB core will handle a hub with no ports...
>  	 */
>  
> -	xhci_create_rhub_port_array(xhci, &xhci->usb2_rhub, flags);
> -	xhci_create_rhub_port_array(xhci, &xhci->usb3_rhub, flags);
> +	ret = xhci_create_rhub_port_array(xhci, &xhci->usb2_rhub, flags);
> +	if (ret)
> +		return ret;
> +
> +	ret = xhci_create_rhub_port_array(xhci, &xhci->usb3_rhub, flags);
> +	if (ret)
> +		return ret;

What about the memory allocated by the first call to
xhci_create_rhub_port_array()?  Is that now lost?  Same for everything
else allocated before these calls, how is that cleaned up properly?

thanks,

greg k-h

  reply	other threads:[~2022-04-21 10:07 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-21  9:42 [PATCH] drivers: usb: host: fix NULL pointer dereferences triggered by unhandled errors in xhci_create_rhub_port_array() Zixuan Fu
2022-04-21 10:07 ` Greg KH [this message]
     [not found]   ` <CAMvdLAPR6JN6PqL_z+MwR=kB5o=+ydBbast9Q-Zgzt_Hwt+UJg@mail.gmail.com>
2022-04-21 11:33     ` Greg KH
2022-04-21 11:55   ` Fu Zixuan
2022-04-21 12:06     ` Greg KH
2022-04-21 12:21       ` Fu Zixuan
2022-04-21 12:52         ` Mathias Nyman
2022-04-21 13:11           ` Fu Zixuan
2022-04-21 13:30             ` Mathias Nyman
2022-04-21 13:32             ` Fu Zixuan
2022-04-21 16:11           ` Greg KH

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YmEs6BqcyM7fgLXg@kroah.com \
    --to=gregkh@linuxfoundation.org \
    --cc=baijiaju1990@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mathias.nyman@intel.com \
    --cc=oslab@tsinghua.edu.cn \
    --cc=r33s3n6@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.