CVE-2025-38349
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
18/07/2025
Last modified:
22/07/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
eventpoll: don&#39;t decrement ep refcount while still holding the ep mutex<br />
<br />
Jann Horn points out that epoll is decrementing the ep refcount and then<br />
doing a<br />
<br />
mutex_unlock(&ep->mtx);<br />
<br />
afterwards. That&#39;s very wrong, because it can lead to a use-after-free.<br />
<br />
That pattern is actually fine for the very last reference, because the<br />
code in question will delay the actual call to "ep_free(ep)" until after<br />
it has unlocked the mutex.<br />
<br />
But it&#39;s wrong for the much subtler "next to last" case when somebody<br />
*else* may also be dropping their reference and free the ep while we&#39;re<br />
still using the mutex.<br />
<br />
Note that this is true even if that other user is also using the same ep<br />
mutex: mutexes, unlike spinlocks, can not be used for object ownership,<br />
even if they guarantee mutual exclusion.<br />
<br />
A mutex "unlock" operation is not atomic, and as one user is still<br />
accessing the mutex as part of unlocking it, another user can come in<br />
and get the now released mutex and free the data structure while the<br />
first user is still cleaning up.<br />
<br />
See our mutex documentation in Documentation/locking/mutex-design.rst,<br />
in particular the section [1] about semantics:<br />
<br />
"mutex_unlock() may access the mutex structure even after it has<br />
internally released the lock already - so it&#39;s not safe for<br />
another context to acquire the mutex and assume that the<br />
mutex_unlock() context is not using the structure anymore"<br />
<br />
So if we drop our ep ref before the mutex unlock, but we weren&#39;t the<br />
last one, we may then unlock the mutex, another user comes in, drops<br />
_their_ reference and releases the &#39;ep&#39; as it now has no users - all<br />
while the mutex_unlock() is still accessing it.<br />
<br />
Fix this by simply moving the ep refcount dropping to outside the mutex:<br />
the refcount itself is atomic, and doesn&#39;t need mutex protection (that&#39;s<br />
the whole _point_ of refcounts: unlike mutexes, they are inherently<br />
about object lifetimes).