vio: Fix signal handling and locking in sysctl path
authorsf <sf@openbsd.org>
Fri, 17 May 2024 16:37:10 +0000 (16:37 +0000)
committersf <sf@openbsd.org>
Fri, 17 May 2024 16:37:10 +0000 (16:37 +0000)
commit68e76eaff5a11098c92d68282d3cedc96ce82010
tree74be4993cc800fa75c2d326534d25d91377021a1
parentaa351fb4f5599d6a6808bc7e95b4d37399774e2c
vio: Fix signal handling and locking in sysctl path

Commits f0b002d01d5 "Release the netlock when sleeping for control
messages in in vioioctl()" and 126b881f71 "Insert a workaround for
per-ifp ioctl being called w/o NET_LOCK()." in vio(4) fixed a deadlock
but may cause a crash with a protection fault trap if addresses are
added/removed concurrently.

The actual issue is that signals are not handled correctly while
sleeping. After a signal, there is a race condition where sc_ctrl_inuse
is first set to FREE and then the interrupt handler sets it to DONE,
causing a hang in the next vio_wait_ctrl() call.

To fix it:

* Revert the NET_LOCK unlocking work-around.

* Remove PCATCH from the sleep call when we wait for control queue,
  avoiding the race with vio_ctrleof(). To ensure that we don't hang
  forever, use a 5 second timeout.

* If the timeout is hit, or if the hypervisor has set the
  DEVICE_NEEDS_RESET status bit, do not try to use the control queue
  until the next ifconfig down/up which resets the device.

* In order to allow reading the device status from device drivers, add a
  new interface to the virtio transport drivers.

* Avoid a crash if there is outgoing traffic while doing ifconfig down.

OK bluhm@
sys/dev/fdt/virtio_mmio.c
sys/dev/pci/virtio_pci.c
sys/dev/pv/if_vio.c
sys/dev/pv/virtiovar.h