casaroli opened a new pull request, #21134: URL: https://github.com/apache/nuttx/pull/21134
## Summary `mld_grpfree()` cancels the poll timer of an MLD group, but not the poll work that the timer queues on LPWORK. If the timer expires shortly before `IPV6_LEAVE_GROUP` frees the group, the work stays in the work queue in freed memory. The worker then crashes in `work_thread()` (data abort at address 0x8) or runs `mld_polldog_work()` on the freed group. `igmp_grpfree()` already cancels its work with `work_cancel_sync()`. The poll work also runs without a lock against `mld_leavegroup()`, so it can start the poll timer again after `mld_grpfree()` cancels it. This PR clears the start-up flag and cancels the poll timer with the device locked, and then cancels the poll work with `work_cancel_sync()`. The poll work now reads the flag and starts the timer with the device locked, so it does not start the timer of a group that is freed. `netdev_unregister()` calls `mld_grpfree_all()` with the device list lock. The poll work takes this lock in `netdev_findbyindex()`, so the wait for the work could deadlock. The groups are now freed after the list lock is released. ## Impact MLD only (`CONFIG_NET_MLD`): no API or Kconfig change. All build modes and architectures. Documentation: no change. ## Testing No test in nuttx-apps covers this (`examples/mld` waits seconds between join and leave). The test is a stand-alone program, `mldrace.c`, with `CONFIG_NET`, `NET_IPv4`, `NET_IPv6`, `NET_UDP`, `NET_LOOPBACK`, `NETDEV_LATEINIT`, `NET_SOCKOPTS`, `NET_ICMPv6` and `NET_MLD`. It runs above the LPWORK priority, joins ff02::125 on `lo` and spins for 1.1 s, so the 1 s poll timer queues its work but the worker cannot run. Then it leaves the group, joins ff02::126 at once (the new group can reuse the freed memory) and sleeps, so the worker runs. It does this three times. | | master | this PR | |---|---|---| | `mldrace.c` on `qemu-armv8a:knsh` (kernel, arm64, QEMU with HVF) | kernel data abort in `lpwork`, FAR 0x8, in the first loop (2 of 2 runs) | 3 loops, no fault | | 40 join/leave loops with the leave 950 to 1045 ms after the join | - | no fault | | ostest, `qemu-armv8a:knsh` and `qemu-armv8a:nsh` (with the network options) | - | status 0 | Build, each OK: `rv-virt:netnsh64` (flat, rv64) with IPv6 and `NET_MLD`, and with `NET_MLD_ROUTER` and `DEBUG_ASSERTIONS`; `rv-virt:knetnsh64` (kernel, rv64) with IPv6 and `NET_MLD`; `mps2-an500:knsh` (protected, Cortex-M3) with IPv6, `NET_MLD` and `NETDEV_LATEINIT`. `tools/checkpatch.sh -c -u -m -g` passes. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
