NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
kern/57965: urtwn(4) command queue can overflow and deadlock
>Number: 57965
>Category: kern
>Synopsis: urtwn(4) command queue can overflow and deadlock
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Feb 26 19:50:00 +0000 2024
>Originator: Taylor R Campbell
>Release: current, 10, 9, 8
>Organization:
The NetURTWN Foundation
>Environment:
>Description:
urtwn_do_async does nothing to prevent the command queue from overflowing, which leads to ring->queued exceeding the number that the task will ever decrement back to zero:
mutex_spin_enter(&sc->sc_task_mtx);
cmd = &ring->cmd[ring->cur];
cmd->cb = cb;
KASSERT(len <= sizeof(cmd->data));
memcpy(cmd->data, arg, len);
ring->cur = (ring->cur + 1) % URTWN_HOST_CMD_RING_COUNT;
/* If there is no pending command already, schedule a task. */
if (!sc->sc_dying && ++ring->queued == 1) {
mutex_spin_exit(&sc->sc_task_mtx);
usb_add_task(sc->sc_udev, &sc->sc_task, USB_TASKQ_DRIVER);
} else
mutex_spin_exit(&sc->sc_task_mtx);
splx(s);
When this happens, urtwn_wait_async hangs forever, so you can't bring the interface down or do anything else with the interface once you make the mistake of trying.
>How-To-Repeat:
exist in a wifi environment that provokes a bunch of state changes (and whatever else) faster than the kernel can process them
>Fix:
(a) stop-gap measure: if ring->queued is already URTWN_HOST_CMD_RING_COUNT, drop the oldest queued command and don't increment ring->queued (but do print a message about overflow)
(b) real fix: stop using a command ring and just use three separate tasks, since two commands of the same type are redundant and can be compressed into one; that way there's no overflow condition
Home |
Main Index |
Thread Index |
Old Index