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]

Reply via email to