diff mbox series

[v2] can: etas_es58x: fix error handling

Message ID 20211115075124.17713-1-paskripkin@gmail.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series [v2] can: etas_es58x: fix error handling | expand

Checks

Context Check Description
netdev/tree_selection success Series ignored based on subject

Commit Message

Pavel Skripkin Nov. 15, 2021, 7:51 a.m. UTC
When register_candev() fails there are 2 possible device states:
NETREG_UNINITIALIZED and NETREG_UNREGISTERED. None of them are suitable
for calling unregister_candev(), because of following checks in
unregister_netdevice_many():

	if (dev->reg_state == NETREG_UNINITIALIZED)
		WARN_ON(1);
...
	BUG_ON(dev->reg_state != NETREG_REGISTERED);

To avoid possible BUG_ON or WARN_ON let's free current netdev before
returning from es58x_init_netdev() and leave others (registered)
net devices for es58x_free_netdevs().

Fixes: 8537257874e9 ("can: etas_es58x: add core support for ETAS ES58X CAN USB interfaces")
Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
---

Changes in v2:
	- Fixed Fixes: tag
	- Moved es58x_dev->netdev[channel_idx] initialization at the end
	  of the function

---
 drivers/net/can/usb/etas_es58x/es58x_core.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Comments

Johan Hovold Nov. 15, 2021, 8:11 a.m. UTC | #1
On Mon, Nov 15, 2021 at 10:51:24AM +0300, Pavel Skripkin wrote:
> When register_candev() fails there are 2 possible device states:
> NETREG_UNINITIALIZED and NETREG_UNREGISTERED. None of them are suitable
> for calling unregister_candev(), because of following checks in
> unregister_netdevice_many():
> 
> 	if (dev->reg_state == NETREG_UNINITIALIZED)
> 		WARN_ON(1);
> ...
> 	BUG_ON(dev->reg_state != NETREG_REGISTERED);
> 
> To avoid possible BUG_ON or WARN_ON let's free current netdev before
> returning from es58x_init_netdev() and leave others (registered)
> net devices for es58x_free_netdevs().
> 
> Fixes: 8537257874e9 ("can: etas_es58x: add core support for ETAS ES58X CAN USB interfaces")
> Signed-off-by: Pavel Skripkin <paskripkin@gmail.com>
> ---
> 
> Changes in v2:
> 	- Fixed Fixes: tag
> 	- Moved es58x_dev->netdev[channel_idx] initialization at the end
> 	  of the function
> 
> ---
>  drivers/net/can/usb/etas_es58x/es58x_core.c | 7 +++++--
>  1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c
> index 96a13c770e4a..b3af8f2e32ac 100644
> --- a/drivers/net/can/usb/etas_es58x/es58x_core.c
> +++ b/drivers/net/can/usb/etas_es58x/es58x_core.c
> @@ -2091,19 +2091,22 @@ static int es58x_init_netdev(struct es58x_device *es58x_dev, int channel_idx)
>  		return -ENOMEM;
>  	}
>  	SET_NETDEV_DEV(netdev, dev);
> -	es58x_dev->netdev[channel_idx] = netdev;
>  	es58x_init_priv(es58x_dev, es58x_priv(netdev), channel_idx);
>  
>  	netdev->netdev_ops = &es58x_netdev_ops;
>  	netdev->flags |= IFF_ECHO;	/* We support local echo */
>  
>  	ret = register_candev(netdev);
> -	if (ret)
> +	if (ret) {
> +		free_candev(netdev);
>  		return ret;
> +	}
>  
>  	netdev_queue_set_dql_min_limit(netdev_get_tx_queue(netdev, 0),
>  				       es58x_dev->param->dql_min_limit);
>  
> +	es58x_dev->netdev[channel_idx] = netdev;
> +

Just a drive-by comment: 

Are you sure about this move of the netdev[channel_idx] initialisation?
What happens if the registered can device is opened before you
initialise the pointer? NULL-deref in es58x_send_msg()?

You generally want the driver data fully initialised before you register
the device so this looks broken.

And either way it is arguably an unrelated change that should go in a
separate patch explaining why it is needed and safe.

>  	return ret;
>  }

Johan
Pavel Skripkin Nov. 15, 2021, 8:15 a.m. UTC | #2
On 11/15/21 11:11, Johan Hovold wrote:
> Just a drive-by comment:
> 
> Are you sure about this move of the netdev[channel_idx] initialisation?
> What happens if the registered can device is opened before you
> initialise the pointer? NULL-deref in es58x_send_msg()?
> 
> You generally want the driver data fully initialised before you register
> the device so this looks broken.
> 
> And either way it is arguably an unrelated change that should go in a
> separate patch explaining why it is needed and safe.
> 


It was suggested by Vincent who is the maintainer of this driver [1].



[1] 
https://lore.kernel.org/linux-can/CAMZ6Rq+orfUuUCCgeWyGc7P0vp3t-yjf_g9H=Jhk43f1zXGfDQ@mail.gmail.com/



With regards,
Pavel Skripkin
Johan Hovold Nov. 15, 2021, 8:16 a.m. UTC | #3
On Mon, Nov 15, 2021 at 11:15:07AM +0300, Pavel Skripkin wrote:
> On 11/15/21 11:11, Johan Hovold wrote:
> > Just a drive-by comment:
> > 
> > Are you sure about this move of the netdev[channel_idx] initialisation?
> > What happens if the registered can device is opened before you
> > initialise the pointer? NULL-deref in es58x_send_msg()?
> > 
> > You generally want the driver data fully initialised before you register
> > the device so this looks broken.
> > 
> > And either way it is arguably an unrelated change that should go in a
> > separate patch explaining why it is needed and safe.
> > 
> 
> 
> It was suggested by Vincent who is the maintainer of this driver [1].

Yeah, I saw that, but that doesn't necessarily mean it is correct.

You're still responsible for the changes you make and need to be able to
argue why they are correct.

Johan
Pavel Skripkin Nov. 15, 2021, 8:30 a.m. UTC | #4
On 11/15/21 11:16, Johan Hovold wrote:
> On Mon, Nov 15, 2021 at 11:15:07AM +0300, Pavel Skripkin wrote:
>> On 11/15/21 11:11, Johan Hovold wrote:
>> > Just a drive-by comment:
>> > 
>> > Are you sure about this move of the netdev[channel_idx] initialisation?
>> > What happens if the registered can device is opened before you
>> > initialise the pointer? NULL-deref in es58x_send_msg()?
>> > 
>> > You generally want the driver data fully initialised before you register
>> > the device so this looks broken.
>> > 
>> > And either way it is arguably an unrelated change that should go in a
>> > separate patch explaining why it is needed and safe.
>> > 
>> 
>> 
>> It was suggested by Vincent who is the maintainer of this driver [1].
> 
> Yeah, I saw that, but that doesn't necessarily mean it is correct.
> 
> You're still responsible for the changes you make and need to be able to
> argue why they are correct.
> 

Sure! I should have check it before sending v2 :( My bad, sorry. I see 
now, that there is possible calltrace which can hit NULL defer.

One thing I am wondering about is why in some code parts there are 
validation checks for es58x_dev->netdev[i] and in others they are missing.

Anyway, it's completely out of scope of current patch, I am going to 
resend v1 with fixed Fixes tag. Thank you for review!





With regards,
Pavel Skripkin
Vincent Mailhol Nov. 15, 2021, 9:24 a.m. UTC | #5
On Mon. 15 Nov 2021 at 17:30, Pavel Skripkin <paskripkin@gmail.com> wrote:
> On 11/15/21 11:16, Johan Hovold wrote:
> > On Mon, Nov 15, 2021 at 11:15:07AM +0300, Pavel Skripkin wrote:
> >> On 11/15/21 11:11, Johan Hovold wrote:
> >> > Just a drive-by comment:
> >> >
> >> > Are you sure about this move of the netdev[channel_idx] initialisation?
> >> > What happens if the registered can device is opened before you
> >> > initialise the pointer? NULL-deref in es58x_send_msg()?
> >> >
> >> > You generally want the driver data fully initialised before you register
> >> > the device so this looks broken.
> >> >
> >> > And either way it is arguably an unrelated change that should go in a
> >> > separate patch explaining why it is needed and safe.
> >> >
> >>
> >>
> >> It was suggested by Vincent who is the maintainer of this driver [1].
> >
> > Yeah, I saw that, but that doesn't necessarily mean it is correct.
> >
> > You're still responsible for the changes you make and need to be able to
> > argue why they are correct.
> >
>
> Sure! I should have check it before sending v2 :( My bad, sorry. I see
> now, that there is possible calltrace which can hit NULL defer.

I should be the one apologizing here. Sorry for the confusion.

> One thing I am wondering about is why in some code parts there are
> validation checks for es58x_dev->netdev[i] and in others they are missing.

There is a validation when it is accessed in a for loop.
It is not guarded in es58x_send_msg() because this function
expects the channel_idx to be a valid index.

Does this answer your wonders?
Pavel Skripkin Nov. 15, 2021, 9:26 a.m. UTC | #6
On 11/15/21 12:24, Vincent MAILHOL wrote:
>> Sure! I should have check it before sending v2 :( My bad, sorry. I see
>> now, that there is possible calltrace which can hit NULL defer.
> 
> I should be the one apologizing here. Sorry for the confusion.
> 
>> One thing I am wondering about is why in some code parts there are
>> validation checks for es58x_dev->netdev[i] and in others they are missing.
> 
> There is a validation when it is accessed in a for loop.
> It is not guarded in es58x_send_msg() because this function
> expects the channel_idx to be a valid index.
> 
> Does this answer your wonders?
> 

Yeah! I have just looked at the code one more time and came up with the 
same idea.

Thank you for confirming and acking my patch :)



With regards,
Pavel Skripkin
diff mbox series

Patch

diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c
index 96a13c770e4a..b3af8f2e32ac 100644
--- a/drivers/net/can/usb/etas_es58x/es58x_core.c
+++ b/drivers/net/can/usb/etas_es58x/es58x_core.c
@@ -2091,19 +2091,22 @@  static int es58x_init_netdev(struct es58x_device *es58x_dev, int channel_idx)
 		return -ENOMEM;
 	}
 	SET_NETDEV_DEV(netdev, dev);
-	es58x_dev->netdev[channel_idx] = netdev;
 	es58x_init_priv(es58x_dev, es58x_priv(netdev), channel_idx);
 
 	netdev->netdev_ops = &es58x_netdev_ops;
 	netdev->flags |= IFF_ECHO;	/* We support local echo */
 
 	ret = register_candev(netdev);
-	if (ret)
+	if (ret) {
+		free_candev(netdev);
 		return ret;
+	}
 
 	netdev_queue_set_dql_min_limit(netdev_get_tx_queue(netdev, 0),
 				       es58x_dev->param->dql_min_limit);
 
+	es58x_dev->netdev[channel_idx] = netdev;
+
 	return ret;
 }