The Linux Kernel has recently addressed a use-after-free vulnerability in the tcp_twsk_unique() function. This vulnerability was reported by Anderson Nascimento who provided an in-depth analysis of the issue.
The Problem
The vulnerability originates from the commit ec94c2696fb ("tcp/dccp: avoid one atomic operation for timewait hashdance"). Since this commit, inet_twsk_hashdance() sets the TIME-WAIT socket's sk_refcnt after putting it into ehash and releasing the bucket lock. This creates a small race window where other threads could try to reuse the port during connect() and call sock_hold() in tcp_twsk_unique() for the TIME-WAIT socket with a zero refcnt.
If this situation occurs, the refcnt that is taken by tcp_twsk_unique() is overwritten and sock_put() will cause an underflow, ultimately triggering a real use-after-free issue somewhere else.
The Solution
To avoid the use-after-free problem, we need to use refcount_inc_not_zero() in tcp_twsk_unique() and give up on reusing the port if it returns false.
The following is a code snippet from the Linux Kernel patch that implements this fix
static bool tcp_twsk_unique(struct sock *sk, struct sock *ssk, __u16 port,
bool *first, bool *second)
{
struct inet_timewait_sock *tw = inet_twsk(ssk);
bool reuse_port;
bool inc_refcnt;
if (!tw)
return false;
*first = false;
*second = false;
inc_refcnt = refcount_inc_not_zero(&ssk->sk_refcnt);
if (!refcount_read(&tw->tw_refcnt))
reuse_port = true;
else
reuse_port = tcp_bind_conflict(sk, inet_twsk(sk)->tw_tb);
if (!reuse_port && inc_refcnt)
sock_put(ssk);
return reuse_port;
}
On their analysis report, Anderson Nascimento documented the vulnerability, which presents the following warning message:
refcount_t: addition on ; use-after-free.
WARNING: CPU: PID: 1039313 at lib/refcount.c:25 refcount_warn_saturate+xe5/x110
CPU: PID: 1039313 Comm: trigger Not tainted 6.8.6-200.fc39.x86_64 #1
[...]
</TASK>
In conclusion, this use-after-free vulnerability in the Linux Kernel has been resolved by using refcount_inc_not_zero() in the tcp_twsk_unique() function. Adopting this approach prevents the underflow issue from occurring and mitigates the risk of a real use-after-free situation elsewhere in the Linux Kernel.
Timeline
Published on: 05/30/2024 16:15:13 UTC
Last modified on: 11/21/2024 09:22:46 UTC