From: Pavel Skripkin <hidden> Date: 2021-09-27 11:20:37
Syzbot reported memory leak in MDIO bus interface, the problem was in
wrong state logic.
MDIOBUS_ALLOCATED indicates 2 states:
1. Bus is only allocated
2. Bus allocated and __mdiobus_register() fails, but
device_register() was called
In case of device_register() has been called we should call put_device()
to correctly free the memory allocated for this device, but mdiobus_free()
was just calling kfree(dev) in case of MDIOBUS_ALLOCATED state
To avoid this behaviour we can add new intermediate state, which means,
that we have called device_regiter(), but failed on any of the next steps.
Clean up process for this state is the same as for MDIOBUS_UNREGISTERED,
but MDIOBUS_UNREGISTERED name does not fit to the logic described above.
Fixes: 46abc02175b3 ("phylib: give mdio buses a device tree presence")
Reported-and-tested-by: syzbot+398e7dc692ddbbb4cfec@syzkaller.appspotmail.com
Signed-off-by: Pavel Skripkin <redacted>
---
drivers/net/phy/mdio_bus.c | 4 +++-
include/linux/phy.h | 1 +
2 files changed, 4 insertions(+), 1 deletion(-)
From: Pavel Skripkin <hidden> Date: 2021-09-27 19:17:58
On 9/27/21 14:20, Pavel Skripkin wrote:
Syzbot reported memory leak in MDIO bus interface, the problem was in
wrong state logic.
MDIOBUS_ALLOCATED indicates 2 states:
1. Bus is only allocated
2. Bus allocated and __mdiobus_register() fails, but
device_register() was called
In case of device_register() has been called we should call put_device()
to correctly free the memory allocated for this device, but mdiobus_free()
was just calling kfree(dev) in case of MDIOBUS_ALLOCATED state
To avoid this behaviour we can add new intermediate state, which means,
that we have called device_regiter(), but failed on any of the next steps.
Clean up process for this state is the same as for MDIOBUS_UNREGISTERED,
but MDIOBUS_UNREGISTERED name does not fit to the logic described above.
Fixes: 46abc02175b3 ("phylib: give mdio buses a device tree presence")
Reported-and-tested-by: syzbot+398e7dc692ddbbb4cfec@syzkaller.appspotmail.com
Signed-off-by: Pavel Skripkin <redacted>
I've just found, that this syzkaller bug has been closed by Yanfei's
patch [1], but Yanfei's Reported-by: is wrong, IMO.
Yanfei's patch fixed other memory leak and it's not related to bug
reported by syzkaller. If you take a look at log [2] you won't find
error message about mii_bus registration failure, i.e the error happened
a bit latter (more precisely in mdiobus_scan()).
Since, Yanfei's patch is already applied, we cannot remove this tag, so
I am informing you about this situation to break possible confusions
about 2 different patches with same Reported-by: tag :)
Thanks
[1]
https://lore.kernel.org/netdev/20210926045313.2267655-1-yanfei.xu@windriver.com/
[2] https://syzkaller.appspot.com/text?tag=CrashLog&x=131c754b300000
With regards,
Pavel Skripkin
From: Pavel Skripkin <hidden> Date: 2021-09-28 20:40:10
This reverts commit ab609f25d19858513919369ff3d9a63c02cd9e2e.
This patch is correct in the sense that we _should_ call device_put() in
case of device_register() failure, but the problem in this code is more
vast.
We need to set bus->state to UNMDIOBUS_REGISTERED before calling
device_register() to correctly release the device in mdiobus_free().
This patch prevents us from doing it, since in case of device_register()
failure put_device() will be called 2 times and it will cause UAF or
something else.
Also, Reported-by: tag in revered commit was wrong, since syzbot
reported different leak in same function.
Link: https://lore.kernel.org/netdev/20210928092657.GI2048@kadam/
Cc: Yanfei Xu <redacted>
Signed-off-by: Pavel Skripkin <redacted>
---
Changes in v2:
Added this revert
---
drivers/net/phy/mdio_bus.c | 1 -
1 file changed, 1 deletion(-)
From: Pavel Skripkin <hidden> Date: 2021-09-28 20:40:27
Syzbot reported memory leak in MDIO bus interface, the problem was in
wrong state logic.
MDIOBUS_ALLOCATED indicates 2 states:
1. Bus is only allocated
2. Bus allocated and __mdiobus_register() fails, but
device_register() was called
In case of device_register() has been called we should call put_device()
to correctly free the memory allocated for this device, but mdiobus_free()
calls just kfree(dev) in case of MDIOBUS_ALLOCATED state
To avoid this behaviour we need to set bus->state to MDIOBUS_UNREGISTERED
_before_ calling device_register(), because put_device() should be
called even in case of device_register() failure.
Link: https://lore.kernel.org/netdev/YVMRWNDZDUOvQjHL@shell.armlinux.org.uk/
Fixes: 46abc02175b3 ("phylib: give mdio buses a device tree presence")
Reported-and-tested-by: syzbot+398e7dc692ddbbb4cfec@syzkaller.appspotmail.com
Signed-off-by: Pavel Skripkin <redacted>
---
Changes in v2:
Removed new state, since MDIOBUS_UNREGISTERED can be used. Also, moved
bus->state initialization _before_ device_register() call, because
Yanfei's patch is reverted in [v2 1/2]
---
drivers/net/phy/mdio_bus.c | 7 +++++++
1 file changed, 7 insertions(+)
@@ -534,6 +534,13 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)bus->dev.groups=NULL;dev_set_name(&bus->dev,"%s",bus->id);+/* We need to set state to MDIOBUS_UNREGISTERED to correctly realese+*thedeviceinmdiobus_free()+*+*Statewillbeupdatedlaterinthisfunctionincaseofsuccess+*/+bus->state==MDIOBUS_UNREGISTERED;+err=device_register(&bus->dev);if(err){pr_err("mii_bus %s failed to register\n",bus->id);
From: Dan Carpenter <hidden> Date: 2021-09-29 06:25:09
On Tue, Sep 28, 2021 at 11:40:15PM +0300, Pavel Skripkin wrote:
Syzbot reported memory leak in MDIO bus interface, the problem was in
wrong state logic.
MDIOBUS_ALLOCATED indicates 2 states:
1. Bus is only allocated
2. Bus allocated and __mdiobus_register() fails, but
device_register() was called
In case of device_register() has been called we should call put_device()
to correctly free the memory allocated for this device, but mdiobus_free()
calls just kfree(dev) in case of MDIOBUS_ALLOCATED state
To avoid this behaviour we need to set bus->state to MDIOBUS_UNREGISTERED
_before_ calling device_register(), because put_device() should be
called even in case of device_register() failure.
Link: https://lore.kernel.org/netdev/YVMRWNDZDUOvQjHL@shell.armlinux.org.uk/
Fixes: 46abc02175b3 ("phylib: give mdio buses a device tree presence")
Reported-and-tested-by: syzbot+398e7dc692ddbbb4cfec@syzkaller.appspotmail.com
Signed-off-by: Pavel Skripkin <redacted>
Thanks!
Reviewed-by: Dan Carpenter <redacted>
regards,
dan carpenter
This reverts commit ab609f25d19858513919369ff3d9a63c02cd9e2e.
This patch is correct in the sense that we_should_ call device_put() in
case of device_register() failure, but the problem in this code is more
vast.
We need to set bus->state to UNMDIOBUS_REGISTERED before calling
device_register() to correctly release the device in mdiobus_free().
This patch prevents us from doing it, since in case of device_register()
failure put_device() will be called 2 times and it will cause UAF or
something else.
Also, Reported-by: tag in revered commit was wrong, since syzbot
reported different leak in same function.
Link:https://lore.kernel.org/netdev/20210928092657.GI2048@kadam/
Cc: Yanfei Xu<redacted>
Signed-off-by: Pavel Skripkin<redacted>
---
Changes in v2:
Added this revert
From: Jakub Kicinski <kuba@kernel.org> Date: 2021-09-29 23:48:45
On Tue, 28 Sep 2021 23:40:15 +0300 Pavel Skripkin wrote:
+ /* We need to set state to MDIOBUS_UNREGISTERED to correctly realese
+ * the device in mdiobus_free()
+ *
+ * State will be updated later in this function in case of success
+ */
+ bus->state == MDIOBUS_UNREGISTERED;
IDK how syzbot has tested it but clearly we should blindly
depend on that.
s/==/=/
Compiler would have told you this.
From: Pavel Skripkin <hidden> Date: 2021-09-30 05:56:01
On 9/30/21 02:48, Jakub Kicinski wrote:
On Tue, 28 Sep 2021 23:40:15 +0300 Pavel Skripkin wrote:
quoted
+ /* We need to set state to MDIOBUS_UNREGISTERED to correctly realese
+ * the device in mdiobus_free()
+ *
+ * State will be updated later in this function in case of success
+ */
+ bus->state == MDIOBUS_UNREGISTERED;
IDK how syzbot has tested it but clearly we should blindly
depend on that.
s/==/=/
Compiler would have told you this.
whooops... sorry about that. syzbot has tested v1. v2 is same, but
without new state (so, the logic in v1 and v2 is the same).
I guess, it's copy-paste error on my side :). Will send v3 this evening
With regards,
Pavel Skripkin