Date: Fri, 24 Oct 2025 10:17:24 -0500 From: Kyle Evans <kevans@FreeBSD.org> To: FreeBSD CURRENT <freebsd-current@freebsd.org> Subject: Re: evdev-induced panic (devfs / destroy_dev race?) Message-ID: <f42f8932-b4fa-47a6-845e-9e8f9d873100@FreeBSD.org> In-Reply-To: <bfdfb864-c8e0-4487-a414-d6dd45ffce9a@FreeBSD.org>
index | next in thread | previous in thread | raw e-mail
On 10/23/25 07:41, Kyle Evans wrote: > Hi, > > Not sure if anyone else has noticed this, but I seem to have scared up an evdev panic: > > [...] >> This was seemingly the result of removing my mouse's USB dongle. Presumably detach revoked the client and > woke it up, which then triggered the above close() from moused to race with destroy_dev() for invoking the > cdevpriv dtor. > > I spent a few minutes thinking about it and didn't really come to a good idea of what the fix might be, > though I suspect there's nothing evdev can really do about it at the moment and we might need to somehow > coordinate this in destroy_dev(). > > Kyle Evans This thread ended up going largely off-list because I was traveling, but to kind of summarize the remainder of the discussion: cdevpriv bits are properly protected by the cdevpriv_mtx, but I pitched the following scenario: Consider threads (U)ser and (D)river: - (U) has called close(2) and is in the middle of devfs_close_f, maybe has bumped the thread refcount - (D) has initiated destroy_dev, waiting for the thread refcount to drop Let's assume now that (U) releases the thread ref. What stops (D) and (U) from subsequently racing to grab the cdevpriv_mtx? I couldn't immediately see anything that might, so let's pretend that (U) wins and peels the cdevpriv off, so now the cdevpriv list is empty. (D) is free to return from destroy_dev while (U) is in the middle of executing the dtor, where we destroy the sx that (U) is trying to acquire. kib created D53303[0] to have destroy_dev() provide a release barrier for cdevpriv destructors so that callers can safely release state as all destructors have run, either by destroy_dev() itself or a concurrent close(2), which I think is the right balance. Thanks, Kyle Evans [0] https://reviews.freebsd.org/D53303help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?f42f8932-b4fa-47a6-845e-9e8f9d873100>
