Summary: | bhyve e1000 broken after r354288 | ||
---|---|---|---|
Product: | Base System | Reporter: | Aleksandr Fedorov <afedorov> |
Component: | bhyve | Assignee: | freebsd-virtualization (Nobody) <virtualization> |
Status: | Closed FIXED | ||
Severity: | Affects Many People | CC: | afedorov, emaste, jhb, vmaffione |
Priority: | --- | ||
Version: | CURRENT | ||
Hardware: | Any | ||
OS: | Any | ||
URL: | https://reviews.freebsd.org/D22286 |
Description
Aleksandr Fedorov
2019-11-08 17:20:09 UTC
Very interesting, thanks for catching it. I think the real problem here (even before r354288) is that nothing prevents a call to kevent(fd, EV_ENABLE) to happen before kevent(fd, EVADD) is called, as you are reporting. On mevent_add() and mevent_update(), mevent_notify() is called to wakeup the I/O thread, that will call kevent(changelist) to update the kernel. A race condition is possible where the client calls mevent_add() and mevent_update(EV_ENABLE) before the I/O thread has the chance to wake up and calls mevent_build()+kevent(changelist), which is exactly what happens in your case. r354288 only makes this race condition more likely (this explains why I did not catch the bug on my machine when I tested e1000). Your fix makes the race condition less likely, but I think it's still there. I tried to rework and simplify mevent.c to make sure EV_ADD is always called before EV_ENABLE or EV_DISABLE. Let me know what you think about that: https://reviews.freebsd.org/D22286 (In reply to Aleksandr Fedorov from comment #0) By the way it makes sense to move the call to netbe_rx_enable() where you suggest, and also call netbe_rx_disable() in the corresponding rx_disable function. A commit references this bug: Author: vmaffione Date: Tue Nov 12 21:07:51 UTC 2019 New revision: 354659 URL: https://svnweb.freebsd.org/changeset/base/354659 Log: bhyve: rework mevent processing to fix a race condition At the end of both mevent_add() and mevent_update(), mevent_notify() is called to wakeup the I/O thread, that will call kevent(changelist) to update the kernel. A race condition is possible where the client calls mevent_add() and mevent_update(EV_ENABLE) before the I/O thread has the chance to wake up and call mevent_build()+kevent(changelist) in response to mevent_add(). The mevent_add() is therefore ignored by the I/O thread, and kevent(fd, EV_ENABLE) is called before kevent(fd, EV_ADD), resuliting in a failure of the kevent(fd, EV_ENABLE) call. PR: 241808 Reviewed by: jhb, markj MFC with: r354288 Differential Revision: https://reviews.freebsd.org/D22286 Changes: head/usr.sbin/bhyve/mevent.c A commit references this bug: Author: vmaffione Date: Tue Nov 26 18:12:13 UTC 2019 New revision: 355117 URL: https://svnweb.freebsd.org/changeset/base/355117 Log: MFC r354659 bhyve: rework mevent processing to fix a race condition At the end of both mevent_add() and mevent_update(), mevent_notify() is called to wakeup the I/O thread, that will call kevent(changelist) to update the kernel. A race condition is possible where the client calls mevent_add() and mevent_update(EV_ENABLE) before the I/O thread has the chance to wake up and call mevent_build()+kevent(changelist) in response to mevent_add(). The mevent_add() is therefore ignored by the I/O thread, and kevent(fd, EV_ENABLE) is called before kevent(fd, EV_ADD), resuliting in a failure of the kevent(fd, EV_ENABLE) call. PR: 241808 Reviewed by: jhb, markj Differential Revision: https://reviews.freebsd.org/D22286 Changes: _U stable/12/ stable/12/usr.sbin/bhyve/mevent.c |