diff mbox series

[11/20] ethernet: ucc_geth: fix use-after-free in ucc_geth_remove()

Message ID 20201205191744.7847-12-rasmus.villemoes@prevas.dk
State Superseded
Headers show
Series ethernet: ucc_geth: assorted fixes and simplifications | expand

Commit Message

Rasmus Villemoes Dec. 5, 2020, 7:17 p.m. UTC
ugeth is the netdiv_priv() part of the netdevice. Accessing the memory
pointed to by ugeth (such as done by ucc_geth_memclean() and the two
of_node_puts) after free_netdev() is thus use-after-free.

Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
---
 drivers/net/ethernet/freescale/ucc_geth.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

Comments

Jakub Kicinski Dec. 5, 2020, 8:48 p.m. UTC | #1
On Sat,  5 Dec 2020 20:17:34 +0100 Rasmus Villemoes wrote:
> -	unregister_netdev(dev);
> -	free_netdev(dev);
>  	ucc_geth_memclean(ugeth);
>  	if (of_phy_is_fixed_link(np))
>  		of_phy_deregister_fixed_link(np);
>  	of_node_put(ugeth->ug_info->tbi_node);
>  	of_node_put(ugeth->ug_info->phy_node);
> +	unregister_netdev(dev);
> +	free_netdev(dev);

Are you sure you want to move the unregister_netdev() as well as the
free?
Rasmus Villemoes Dec. 5, 2020, 9:04 p.m. UTC | #2
On 05/12/2020 21.48, Jakub Kicinski wrote:
> On Sat,  5 Dec 2020 20:17:34 +0100 Rasmus Villemoes wrote:
>> -	unregister_netdev(dev);
>> -	free_netdev(dev);
>>  	ucc_geth_memclean(ugeth);
>>  	if (of_phy_is_fixed_link(np))
>>  		of_phy_deregister_fixed_link(np);
>>  	of_node_put(ugeth->ug_info->tbi_node);
>>  	of_node_put(ugeth->ug_info->phy_node);
>> +	unregister_netdev(dev);
>> +	free_netdev(dev);
> 
> Are you sure you want to move the unregister_netdev() as well as the
> free?
> 

Hm, dunno, I don't think it's needed per se, but it also shouldn't hurt
from what I can tell. It seems more natural that they go together, but
if you prefer a minimal patch that's of course also possible.

I only noticed because I needed to add a free of the ug_info in a later
patch.

Rasmus
Jakub Kicinski Dec. 5, 2020, 9:19 p.m. UTC | #3
On Sat, 5 Dec 2020 22:04:28 +0100 Rasmus Villemoes wrote:
> On 05/12/2020 21.48, Jakub Kicinski wrote:
> > On Sat,  5 Dec 2020 20:17:34 +0100 Rasmus Villemoes wrote:  
> >> -	unregister_netdev(dev);
> >> -	free_netdev(dev);
> >>  	ucc_geth_memclean(ugeth);
> >>  	if (of_phy_is_fixed_link(np))
> >>  		of_phy_deregister_fixed_link(np);
> >>  	of_node_put(ugeth->ug_info->tbi_node);
> >>  	of_node_put(ugeth->ug_info->phy_node);
> >> +	unregister_netdev(dev);
> >> +	free_netdev(dev);  
> > 
> > Are you sure you want to move the unregister_netdev() as well as the
> > free?
> 
> Hm, dunno, I don't think it's needed per se, but it also shouldn't hurt
> from what I can tell. It seems more natural that they go together, but
> if you prefer a minimal patch that's of course also possible.

I was concerned about the fact that we free things and release
references while the device may still be up (given that it's
unregister_netdev() that will take it down).

> I only noticed because I needed to add a free of the ug_info in a later
> patch.
Rasmus Villemoes Dec. 5, 2020, 9:35 p.m. UTC | #4
On 05/12/2020 22.19, Jakub Kicinski wrote:
> On Sat, 5 Dec 2020 22:04:28 +0100 Rasmus Villemoes wrote:
>> On 05/12/2020 21.48, Jakub Kicinski wrote:
>>> On Sat,  5 Dec 2020 20:17:34 +0100 Rasmus Villemoes wrote:  
>>>> -	unregister_netdev(dev);
>>>> -	free_netdev(dev);
>>>>  	ucc_geth_memclean(ugeth);
>>>>  	if (of_phy_is_fixed_link(np))
>>>>  		of_phy_deregister_fixed_link(np);
>>>>  	of_node_put(ugeth->ug_info->tbi_node);
>>>>  	of_node_put(ugeth->ug_info->phy_node);
>>>> +	unregister_netdev(dev);
>>>> +	free_netdev(dev);  
>>>
>>> Are you sure you want to move the unregister_netdev() as well as the
>>> free?
>>
>> Hm, dunno, I don't think it's needed per se, but it also shouldn't hurt
>> from what I can tell. It seems more natural that they go together, but
>> if you prefer a minimal patch that's of course also possible.
> 
> I was concerned about the fact that we free things and release
> references while the device may still be up (given that it's
> unregister_netdev() that will take it down).

I guess you're right. I'll fix it locally (and pull the patch earlier)
and wait a few days with sending an updated version to give Li Yang some
time to say if he wants to handle the series or not.

Thanks,
Rasmus
Rasmus Villemoes Dec. 5, 2020, 9:50 p.m. UTC | #5
> I only noticed because I needed to add a free of the ug_info in a later
> patch.

Where, ironically, I add a use-after-free bug by freeing ug_info before
the ucc_geth_memclean() call.

:facepalm:
diff mbox series

Patch

diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index b132fcfc7c17..ba911d05d36d 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -3895,13 +3895,13 @@  static int ucc_geth_remove(struct platform_device* ofdev)
 	struct ucc_geth_private *ugeth = netdev_priv(dev);
 	struct device_node *np = ofdev->dev.of_node;
 
-	unregister_netdev(dev);
-	free_netdev(dev);
 	ucc_geth_memclean(ugeth);
 	if (of_phy_is_fixed_link(np))
 		of_phy_deregister_fixed_link(np);
 	of_node_put(ugeth->ug_info->tbi_node);
 	of_node_put(ugeth->ug_info->phy_node);
+	unregister_netdev(dev);
+	free_netdev(dev);
 
 	return 0;
 }