ARM: at91: pm: fix imbalanced reference counter for ethernet devices

Message ID 20230518062511.2988500-1-claudiu.beznea@microchip.com
State New
Headers
Series ARM: at91: pm: fix imbalanced reference counter for ethernet devices |

Commit Message

Claudiu Beznea May 18, 2023, 6:25 a.m. UTC
  The of_find_device_by_node() function is returning a struct platform_device
object with the embedded struct device member's reference counter
incremented. This needs to be dropped when done with the platform device
returned by of_find_device_by_node().

at91_pm_eth_quirk_is_valid() calls of_find_device_by_node() on
suspend and resume path. On suspend it calls of_find_device_by_node() and
on resume and failure paths it drops the counter of
struct platform_device::dev.

In case ethernet device may not wakeup there is a put_device() on
at91_pm_eth_quirk_is_valid() which is wrong as it colides with
put_device() on resume path leading to the reference counter of struct
device embedded in struct platform_device to be messed, the following
stack trace to be displayed (after 5 consecutive suspend/resume cycles)
and the execution to hang:

WARNING: CPU: 0 PID: 378 at lib/refcount.c:25 0xc07ffc08
refcount_t: addition on 0; use-after-free.
Modules linked in:
CPU: 0 PID: 378 Comm: sh Not tainted 6.1.22-linux4microchip-2023.04-rc3+ #7
Hardware name: Microchip SAMA7
Function entered at [<c010c134>] from [<c010993c>]
Function entered at [<c010993c>] from [<c0823754>]
Function entered at [<c0823754>] from [<c01162ac>]
Function entered at [<c01162ac>] from [<c0116340>]
Function entered at [<c0116340>] from [<c07ffc08>]
Function entered at [<c07ffc08>] from [<c045fe88>]
Function entered at [<c045fe88>] from [<c046004c>]
Function entered at [<c046004c>] from [<c0141e94>]
Function entered at [<c0141e94>] from [<c0142448>]
Function entered at [<c0142448>] from [<c0140da8>]
Function entered at [<c0140da8>] from [<c023dba0>]
Function entered at [<c023dba0>] from [<c01d0700>]
Function entered at [<c01d0700>] from [<c01d092c>]
Function entered at [<c01d092c>] from [<c0100060>]
Exception stack(0xe0e81fa8 to 0xe0e81ff0)
1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
---[ end trace 0000000000000000 ]---
------------[ cut here ]------------
WARNING: CPU: 0 PID: 378 at lib/refcount.c:28 0xc045fef4
refcount_t: underflow; use-after-free.
Modules linked in:
CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
Hardware name: Microchip SAMA7
Function entered at [<c010c134>] from [<c010993c>]
Function entered at [<c010993c>] from [<c0823754>]
Function entered at [<c0823754>] from [<c01162ac>]
Function entered at [<c01162ac>] from [<c0116340>]
Function entered at [<c0116340>] from [<c045fef4>]
Function entered at [<c045fef4>] from [<c046004c>]
Function entered at [<c046004c>] from [<c0141e94>]
Function entered at [<c0141e94>] from [<c0142448>]
Function entered at [<c0142448>] from [<c0140da8>]
Function entered at [<c0140da8>] from [<c023dba0>]
Function entered at [<c023dba0>] from [<c01d0700>]
Function entered at [<c01d0700>] from [<c01d092c>]
Function entered at [<c01d092c>] from [<c0100060>]
Exception stack(0xe0e81fa8 to 0xe0e81ff0)
1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
---[ end trace 0000000000000000 ]---
------------[ cut here ]------------
WARNING: CPU: 0 PID: 378 at lib/refcount.c:22 0xc07ffbf4
refcount_t: saturated; leaking memory.
Modules linked in:
CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
Hardware name: Microchip SAMA7
Function entered at [<c010c134>] from [<c010993c>]
Function entered at [<c010993c>] from [<c0823754>]
Function entered at [<c0823754>] from [<c01162ac>]
Function entered at [<c01162ac>] from [<c0116340>]
Function entered at [<c0116340>] from [<c07ffbf4>]
Function entered at [<c07ffbf4>] from [<c045eaa0>]
Function entered at [<c045eaa0>] from [<c045fcc4>]
Function entered at [<c045fcc4>] from [<c045fee4>]
Function entered at [<c045fee4>] from [<c046004c>]
Function entered at [<c046004c>] from [<c0141e94>]
Function entered at [<c0141e94>] from [<c0142448>]
Function entered at [<c0142448>] from [<c0140da8>]
Function entered at [<c0140da8>] from [<c023dba0>]
Function entered at [<c023dba0>] from [<c01d0700>]
Function entered at [<c01d0700>] from [<c01d092c>]
Function entered at [<c01d092c>] from [<c0100060>]
Exception stack(0xe0e81fa8 to 0xe0e81ff0)
1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
---[ end trace 0000000000000000 ]---
------------[ cut here ]------------
WARNING: CPU: 0 PID: 378 at kernel/irq/chip.c:241 0xc014be2c
Modules linked in:
CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
Hardware name: Microchip SAMA7
Function entered at [<c010c134>] from [<c010993c>]
Function entered at [<c010993c>] from [<c0823754>]
Function entered at [<c0823754>] from [<c01162ac>]
Function entered at [<c01162ac>] from [<c011637c>]
Function entered at [<c011637c>] from [<c014be2c>]
Function entered at [<c014be2c>] from [<c014f808>]
Function entered at [<c014f808>] from [<c0460050>]
Function entered at [<c0460050>] from [<c0141e94>]
Function entered at [<c0141e94>] from [<c0142448>]
Function entered at [<c0142448>] from [<c0140da8>]
Function entered at [<c0140da8>] from [<c023dba0>]
Function entered at [<c023dba0>] from [<c01d0700>]
Function entered at [<c01d0700>] from [<c01d092c>]
Function entered at [<c01d092c>] from [<c0100060>]
Exception stack(0xe0e81fa8 to 0xe0e81ff0)
1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
---[ end trace 0000000000000000 ]---
at_xdmac e1200000.dma-controller: controller in mem2mem mode.
------------[ cut here ]------------
WARNING: CPU: 0 PID: 378 at lib/kobject.c:634 0xc07ffbe8
kobject: '$���"����L��L��' (a3ba4c7d): is not initialized, yet kobject_get() is being called.
Modules linked in:
CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
Hardware name: Microchip SAMA7
Function entered at [<c010c134>] from [<c010993c>]
Function entered at [<c010993c>] from [<c0823754>]
Function entered at [<c0823754>] from [<c01162ac>]
Function entered at [<c01162ac>] from [<c0116340>]
Function entered at [<c0116340>] from [<c07ffbe8>]
Function entered at [<c07ffbe8>] from [<c0460300>]
Function entered at [<c0460300>] from [<c0460634>]
Function entered at [<c0460634>] from [<c0141ed4>]
Function entered at [<c0141ed4>] from [<c0142448>]
Function entered at [<c0142448>] from [<c0140da8>]
Function entered at [<c0140da8>] from [<c023dba0>]
Function entered at [<c023dba0>] from [<c01d0700>]
Function entered at [<c01d0700>] from [<c01d092c>]
Function entered at [<c01d092c>] from [<c0100060>]
Exception stack(0xe0e81fa8 to 0xe0e81ff0)
1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
---[ end trace 0000000000000000 ]---
------------[ cut here ]------------
WARNING: CPU: 0 PID: 378 at lib/kobject.c:728 0xc07ffd7c
kobject: '$���"����L��L��' (a3ba4c7d): is not initialized, yet kobject_put() is being called.
Modules linked in:
CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
Hardware name: Microchip SAMA7
Function entered at [<c010c134>] from [<c010993c>]
Function entered at [<c010993c>] from [<c0823754>]
Function entered at [<c0823754>] from [<c01162ac>]
Function entered at [<c01162ac>] from [<c0116340>]
Function entered at [<c0116340>] from [<c07ffd7c>]
Function entered at [<c07ffd7c>] from [<c0460384>]
Function entered at [<c0460384>] from [<c0460634>]
Function entered at [<c0460634>] from [<c0141ed4>]
Function entered at [<c0141ed4>] from [<c0142448>]
Function entered at [<c0142448>] from [<c0140da8>]
Function entered at [<c0140da8>] from [<c023dba0>]
Function entered at [<c023dba0>] from [<c01d0700>]
Function entered at [<c01d0700>] from [<c01d092c>]
Function entered at [<c01d092c>] from [<c0100060>]
Exception stack(0xe0e81fa8 to 0xe0e81ff0)
1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
---[ end trace 0000000000000000 ]---
------------[ cut here ]------------
WARNING: CPU: 0 PID: 378 at lib/kobject.c:634 0xc07ffbe8
kobject: '�Z����@Ą�?��8�H�Ĕ����UC�' (6407eb2a): is not initialized, yet kobject_get() is being called.
Modules linked in:
CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
Hardware name: Microchip SAMA7
Function entered at [<c010c134>] from [<c010993c>]
Function entered at [<c010993c>] from [<c0823754>]
Function entered at [<c0823754>] from [<c01162ac>]
Function entered at [<c01162ac>] from [<c0116340>]
Function entered at [<c0116340>] from [<c07ffbe8>]
Function entered at [<c07ffbe8>] from [<c0460300>]
Function entered at [<c0460300>] from [<c0460634>]
Function entered at [<c0460634>] from [<c0141ed4>]
Function entered at [<c0141ed4>] from [<c0142448>]
Function entered at [<c0142448>] from [<c0140da8>]
Function entered at [<c0140da8>] from [<c023dba0>]
Function entered at [<c023dba0>] from [<c01d0700>]
Function entered at [<c01d0700>] from [<c01d092c>]
Function entered at [<c01d092c>] from [<c0100060>]
Exception stack(0xe0e81fa8 to 0xe0e81ff0)
1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
---[ end trace 0000000000000000 ]---

Along with this the error path of at91_pm_config_quirks() had been also
adapted to decrement propertly the reference counter of struct device
embedded in struct platform_device.

Fixes: b7fc72c63399 ("ARM: at91: pm: add quirks for pm")
Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
---
 arch/arm/mach-at91/pm.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)
  

Comments

Nicolas Ferre May 22, 2023, 9:07 a.m. UTC | #1
On 18/05/2023 at 08:25, Claudiu Beznea wrote:
> The of_find_device_by_node() function is returning a struct platform_device
> object with the embedded struct device member's reference counter
> incremented. This needs to be dropped when done with the platform device
> returned by of_find_device_by_node().
> 
> at91_pm_eth_quirk_is_valid() calls of_find_device_by_node() on
> suspend and resume path. On suspend it calls of_find_device_by_node() and
> on resume and failure paths it drops the counter of
> struct platform_device::dev.
> 
> In case ethernet device may not wakeup there is a put_device() on
> at91_pm_eth_quirk_is_valid() which is wrong as it colides with
> put_device() on resume path leading to the reference counter of struct
> device embedded in struct platform_device to be messed, the following
> stack trace to be displayed (after 5 consecutive suspend/resume cycles)
> and the execution to hang:
> 
> WARNING: CPU: 0 PID: 378 at lib/refcount.c:25 0xc07ffc08
> refcount_t: addition on 0; use-after-free.
> Modules linked in:
> CPU: 0 PID: 378 Comm: sh Not tainted 6.1.22-linux4microchip-2023.04-rc3+ #7
> Hardware name: Microchip SAMA7
> Function entered at [<c010c134>] from [<c010993c>]
> Function entered at [<c010993c>] from [<c0823754>]
> Function entered at [<c0823754>] from [<c01162ac>]
> Function entered at [<c01162ac>] from [<c0116340>]
> Function entered at [<c0116340>] from [<c07ffc08>]
> Function entered at [<c07ffc08>] from [<c045fe88>]
> Function entered at [<c045fe88>] from [<c046004c>]
> Function entered at [<c046004c>] from [<c0141e94>]
> Function entered at [<c0141e94>] from [<c0142448>]
> Function entered at [<c0142448>] from [<c0140da8>]
> Function entered at [<c0140da8>] from [<c023dba0>]
> Function entered at [<c023dba0>] from [<c01d0700>]
> Function entered at [<c01d0700>] from [<c01d092c>]
> Function entered at [<c01d092c>] from [<c0100060>]
> Exception stack(0xe0e81fa8 to 0xe0e81ff0)
> 1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
> 1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
> 1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
> ---[ end trace 0000000000000000 ]---
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 378 at lib/refcount.c:28 0xc045fef4
> refcount_t: underflow; use-after-free.
> Modules linked in:
> CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
> Hardware name: Microchip SAMA7
> Function entered at [<c010c134>] from [<c010993c>]
> Function entered at [<c010993c>] from [<c0823754>]
> Function entered at [<c0823754>] from [<c01162ac>]
> Function entered at [<c01162ac>] from [<c0116340>]
> Function entered at [<c0116340>] from [<c045fef4>]
> Function entered at [<c045fef4>] from [<c046004c>]
> Function entered at [<c046004c>] from [<c0141e94>]
> Function entered at [<c0141e94>] from [<c0142448>]
> Function entered at [<c0142448>] from [<c0140da8>]
> Function entered at [<c0140da8>] from [<c023dba0>]
> Function entered at [<c023dba0>] from [<c01d0700>]
> Function entered at [<c01d0700>] from [<c01d092c>]
> Function entered at [<c01d092c>] from [<c0100060>]
> Exception stack(0xe0e81fa8 to 0xe0e81ff0)
> 1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
> 1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
> 1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
> ---[ end trace 0000000000000000 ]---
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 378 at lib/refcount.c:22 0xc07ffbf4
> refcount_t: saturated; leaking memory.
> Modules linked in:
> CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
> Hardware name: Microchip SAMA7
> Function entered at [<c010c134>] from [<c010993c>]
> Function entered at [<c010993c>] from [<c0823754>]
> Function entered at [<c0823754>] from [<c01162ac>]
> Function entered at [<c01162ac>] from [<c0116340>]
> Function entered at [<c0116340>] from [<c07ffbf4>]
> Function entered at [<c07ffbf4>] from [<c045eaa0>]
> Function entered at [<c045eaa0>] from [<c045fcc4>]
> Function entered at [<c045fcc4>] from [<c045fee4>]
> Function entered at [<c045fee4>] from [<c046004c>]
> Function entered at [<c046004c>] from [<c0141e94>]
> Function entered at [<c0141e94>] from [<c0142448>]
> Function entered at [<c0142448>] from [<c0140da8>]
> Function entered at [<c0140da8>] from [<c023dba0>]
> Function entered at [<c023dba0>] from [<c01d0700>]
> Function entered at [<c01d0700>] from [<c01d092c>]
> Function entered at [<c01d092c>] from [<c0100060>]
> Exception stack(0xe0e81fa8 to 0xe0e81ff0)
> 1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
> 1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
> 1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
> ---[ end trace 0000000000000000 ]---
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 378 at kernel/irq/chip.c:241 0xc014be2c
> Modules linked in:
> CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
> Hardware name: Microchip SAMA7
> Function entered at [<c010c134>] from [<c010993c>]
> Function entered at [<c010993c>] from [<c0823754>]
> Function entered at [<c0823754>] from [<c01162ac>]
> Function entered at [<c01162ac>] from [<c011637c>]
> Function entered at [<c011637c>] from [<c014be2c>]
> Function entered at [<c014be2c>] from [<c014f808>]
> Function entered at [<c014f808>] from [<c0460050>]
> Function entered at [<c0460050>] from [<c0141e94>]
> Function entered at [<c0141e94>] from [<c0142448>]
> Function entered at [<c0142448>] from [<c0140da8>]
> Function entered at [<c0140da8>] from [<c023dba0>]
> Function entered at [<c023dba0>] from [<c01d0700>]
> Function entered at [<c01d0700>] from [<c01d092c>]
> Function entered at [<c01d092c>] from [<c0100060>]
> Exception stack(0xe0e81fa8 to 0xe0e81ff0)
> 1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
> 1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
> 1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
> ---[ end trace 0000000000000000 ]---
> at_xdmac e1200000.dma-controller: controller in mem2mem mode.
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 378 at lib/kobject.c:634 0xc07ffbe8
> kobject: '$���"����L��L��' (a3ba4c7d): is not initialized, yet kobject_get() is being called.
> Modules linked in:
> CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
> Hardware name: Microchip SAMA7
> Function entered at [<c010c134>] from [<c010993c>]
> Function entered at [<c010993c>] from [<c0823754>]
> Function entered at [<c0823754>] from [<c01162ac>]
> Function entered at [<c01162ac>] from [<c0116340>]
> Function entered at [<c0116340>] from [<c07ffbe8>]
> Function entered at [<c07ffbe8>] from [<c0460300>]
> Function entered at [<c0460300>] from [<c0460634>]
> Function entered at [<c0460634>] from [<c0141ed4>]
> Function entered at [<c0141ed4>] from [<c0142448>]
> Function entered at [<c0142448>] from [<c0140da8>]
> Function entered at [<c0140da8>] from [<c023dba0>]
> Function entered at [<c023dba0>] from [<c01d0700>]
> Function entered at [<c01d0700>] from [<c01d092c>]
> Function entered at [<c01d092c>] from [<c0100060>]
> Exception stack(0xe0e81fa8 to 0xe0e81ff0)
> 1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
> 1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
> 1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
> ---[ end trace 0000000000000000 ]---
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 378 at lib/kobject.c:728 0xc07ffd7c
> kobject: '$���"����L��L��' (a3ba4c7d): is not initialized, yet kobject_put() is being called.
> Modules linked in:
> CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
> Hardware name: Microchip SAMA7
> Function entered at [<c010c134>] from [<c010993c>]
> Function entered at [<c010993c>] from [<c0823754>]
> Function entered at [<c0823754>] from [<c01162ac>]
> Function entered at [<c01162ac>] from [<c0116340>]
> Function entered at [<c0116340>] from [<c07ffd7c>]
> Function entered at [<c07ffd7c>] from [<c0460384>]
> Function entered at [<c0460384>] from [<c0460634>]
> Function entered at [<c0460634>] from [<c0141ed4>]
> Function entered at [<c0141ed4>] from [<c0142448>]
> Function entered at [<c0142448>] from [<c0140da8>]
> Function entered at [<c0140da8>] from [<c023dba0>]
> Function entered at [<c023dba0>] from [<c01d0700>]
> Function entered at [<c01d0700>] from [<c01d092c>]
> Function entered at [<c01d092c>] from [<c0100060>]
> Exception stack(0xe0e81fa8 to 0xe0e81ff0)
> 1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
> 1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
> 1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
> ---[ end trace 0000000000000000 ]---
> ------------[ cut here ]------------
> WARNING: CPU: 0 PID: 378 at lib/kobject.c:634 0xc07ffbe8
> kobject: '�Z����@Ą�?��8�H�Ĕ����UC�' (6407eb2a): is not initialized, yet kobject_get() is being called.
> Modules linked in:
> CPU: 0 PID: 378 Comm: sh Tainted: G        W          6.1.22-linux4microchip-2023.04-rc3+ #7
> Hardware name: Microchip SAMA7
> Function entered at [<c010c134>] from [<c010993c>]
> Function entered at [<c010993c>] from [<c0823754>]
> Function entered at [<c0823754>] from [<c01162ac>]
> Function entered at [<c01162ac>] from [<c0116340>]
> Function entered at [<c0116340>] from [<c07ffbe8>]
> Function entered at [<c07ffbe8>] from [<c0460300>]
> Function entered at [<c0460300>] from [<c0460634>]
> Function entered at [<c0460634>] from [<c0141ed4>]
> Function entered at [<c0141ed4>] from [<c0142448>]
> Function entered at [<c0142448>] from [<c0140da8>]
> Function entered at [<c0140da8>] from [<c023dba0>]
> Function entered at [<c023dba0>] from [<c01d0700>]
> Function entered at [<c01d0700>] from [<c01d092c>]
> Function entered at [<c01d092c>] from [<c0100060>]
> Exception stack(0xe0e81fa8 to 0xe0e81ff0)
> 1fa0:                   00000004 0057c668 00000001 0057c668 00000004 00000000
> 1fc0: 00000004 0057c668 b6ecaba0 00000004 b6f4c0e0 b6ecb15c 00000000 00000000
> 1fe0: 005456f0 beb3a788 b6dcfac4 b6e3bab8
> ---[ end trace 0000000000000000 ]---
> 
> Along with this the error path of at91_pm_config_quirks() had been also
> adapted to decrement propertly the reference counter of struct device
> embedded in struct platform_device.
> 
> Fixes: b7fc72c63399 ("ARM: at91: pm: add quirks for pm")
> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>

Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Thanks for this fix Claudiu. Best regards,
   Nicolas

> ---
>   arch/arm/mach-at91/pm.c | 20 +++++++++-----------
>   1 file changed, 9 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
> index 60dc56d8acfb..437dd0352fd4 100644
> --- a/arch/arm/mach-at91/pm.c
> +++ b/arch/arm/mach-at91/pm.c
> @@ -334,16 +334,14 @@ static bool at91_pm_eth_quirk_is_valid(struct at91_pm_quirk_eth *eth)
>   		pdev = of_find_device_by_node(eth->np);
>   		if (!pdev)
>   			return false;
> +		/* put_device(eth->dev) is called at the end of suspend. */
>   		eth->dev = &pdev->dev;
>   	}
>   
>   	/* No quirks if device isn't a wakeup source. */
> -	if (!device_may_wakeup(eth->dev)) {
> -		put_device(eth->dev);
> +	if (!device_may_wakeup(eth->dev))
>   		return false;
> -	}
>   
> -	/* put_device(eth->dev) is called at the end of suspend. */
>   	return true;
>   }
>   
> @@ -439,14 +437,14 @@ static int at91_pm_config_quirks(bool suspend)
>   				pr_err("AT91: PM: failed to enable %s clocks\n",
>   				       j == AT91_PM_G_ETH ? "geth" : "eth");
>   			}
> -		} else {
> -			/*
> -			 * Release the reference to eth->dev taken in
> -			 * at91_pm_eth_quirk_is_valid().
> -			 */
> -			put_device(eth->dev);
> -			eth->dev = NULL;
>   		}
> +
> +		/*
> +		 * Release the reference to eth->dev taken in
> +		 * at91_pm_eth_quirk_is_valid().
> +		 */
> +		put_device(eth->dev);
> +		eth->dev = NULL;
>   	}
>   
>   	return ret;
  
Russell King (Oracle) May 22, 2023, 9:11 a.m. UTC | #2
On Thu, May 18, 2023 at 09:25:11AM +0300, Claudiu Beznea wrote:
> WARNING: CPU: 0 PID: 378 at lib/refcount.c:25 0xc07ffc08
> refcount_t: addition on 0; use-after-free.
> Modules linked in:
> CPU: 0 PID: 378 Comm: sh Not tainted 6.1.22-linux4microchip-2023.04-rc3+ #7
> Hardware name: Microchip SAMA7
> Function entered at [<c010c134>] from [<c010993c>]
> Function entered at [<c010993c>] from [<c0823754>]
> Function entered at [<c0823754>] from [<c01162ac>]
> Function entered at [<c01162ac>] from [<c0116340>]
> Function entered at [<c0116340>] from [<c07ffc08>]
> Function entered at [<c07ffc08>] from [<c045fe88>]
> Function entered at [<c045fe88>] from [<c046004c>]
> Function entered at [<c046004c>] from [<c0141e94>]
> Function entered at [<c0141e94>] from [<c0142448>]
> Function entered at [<c0142448>] from [<c0140da8>]
> Function entered at [<c0140da8>] from [<c023dba0>]
> Function entered at [<c023dba0>] from [<c01d0700>]
> Function entered at [<c01d0700>] from [<c01d092c>]
> Function entered at [<c01d092c>] from [<c0100060>]

There is no point what so ever including the backtrace in your commit
message - the hex numbers here are specific to your kernel build and
are meaningless for everyone else.

Please either convert them to symbolic information so that they are
meaningful to other people, or omit them. Thanks.
  
Claudiu Beznea May 24, 2023, 8:49 a.m. UTC | #3
On 18.05.2023 09:25, Claudiu Beznea wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe
> 
> The of_find_device_by_node() function is returning a struct platform_device
> object with the embedded struct device member's reference counter
> incremented. This needs to be dropped when done with the platform device
> returned by of_find_device_by_node().
> 
> at91_pm_eth_quirk_is_valid() calls of_find_device_by_node() on
> suspend and resume path. On suspend it calls of_find_device_by_node() and
> on resume and failure paths it drops the counter of
> struct platform_device::dev.
> 
> In case ethernet device may not wakeup there is a put_device() on
> at91_pm_eth_quirk_is_valid() which is wrong as it colides with
> put_device() on resume path leading to the reference counter of struct
> device embedded in struct platform_device to be messed, the following
> stack trace to be displayed (after 5 consecutive suspend/resume cycles)
> and the execution to hang:
> 

[ ... ]

> 
> Along with this the error path of at91_pm_config_quirks() had been also
> adapted to decrement propertly the reference counter of struct device
> embedded in struct platform_device.
> 
> Fixes: b7fc72c63399 ("ARM: at91: pm: add quirks for pm")
> Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>

Applied to at91-fixes (after removing useless stack traces in commit
message), thanks!

> ---
>  arch/arm/mach-at91/pm.c | 20 +++++++++-----------
>  1 file changed, 9 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
> index 60dc56d8acfb..437dd0352fd4 100644
> --- a/arch/arm/mach-at91/pm.c
> +++ b/arch/arm/mach-at91/pm.c
> @@ -334,16 +334,14 @@ static bool at91_pm_eth_quirk_is_valid(struct at91_pm_quirk_eth *eth)
>                 pdev = of_find_device_by_node(eth->np);
>                 if (!pdev)
>                         return false;
> +               /* put_device(eth->dev) is called at the end of suspend. */
>                 eth->dev = &pdev->dev;
>         }
> 
>         /* No quirks if device isn't a wakeup source. */
> -       if (!device_may_wakeup(eth->dev)) {
> -               put_device(eth->dev);
> +       if (!device_may_wakeup(eth->dev))
>                 return false;
> -       }
> 
> -       /* put_device(eth->dev) is called at the end of suspend. */
>         return true;
>  }
> 
> @@ -439,14 +437,14 @@ static int at91_pm_config_quirks(bool suspend)
>                                 pr_err("AT91: PM: failed to enable %s clocks\n",
>                                        j == AT91_PM_G_ETH ? "geth" : "eth");
>                         }
> -               } else {
> -                       /*
> -                        * Release the reference to eth->dev taken in
> -                        * at91_pm_eth_quirk_is_valid().
> -                        */
> -                       put_device(eth->dev);
> -                       eth->dev = NULL;
>                 }
> +
> +               /*
> +                * Release the reference to eth->dev taken in
> +                * at91_pm_eth_quirk_is_valid().
> +                */
> +               put_device(eth->dev);
> +               eth->dev = NULL;
>         }
> 
>         return ret;
> --
> 2.34.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
  

Patch

diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c
index 60dc56d8acfb..437dd0352fd4 100644
--- a/arch/arm/mach-at91/pm.c
+++ b/arch/arm/mach-at91/pm.c
@@ -334,16 +334,14 @@  static bool at91_pm_eth_quirk_is_valid(struct at91_pm_quirk_eth *eth)
 		pdev = of_find_device_by_node(eth->np);
 		if (!pdev)
 			return false;
+		/* put_device(eth->dev) is called at the end of suspend. */
 		eth->dev = &pdev->dev;
 	}
 
 	/* No quirks if device isn't a wakeup source. */
-	if (!device_may_wakeup(eth->dev)) {
-		put_device(eth->dev);
+	if (!device_may_wakeup(eth->dev))
 		return false;
-	}
 
-	/* put_device(eth->dev) is called at the end of suspend. */
 	return true;
 }
 
@@ -439,14 +437,14 @@  static int at91_pm_config_quirks(bool suspend)
 				pr_err("AT91: PM: failed to enable %s clocks\n",
 				       j == AT91_PM_G_ETH ? "geth" : "eth");
 			}
-		} else {
-			/*
-			 * Release the reference to eth->dev taken in
-			 * at91_pm_eth_quirk_is_valid().
-			 */
-			put_device(eth->dev);
-			eth->dev = NULL;
 		}
+
+		/*
+		 * Release the reference to eth->dev taken in
+		 * at91_pm_eth_quirk_is_valid().
+		 */
+		put_device(eth->dev);
+		eth->dev = NULL;
 	}
 
 	return ret;