From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4D11E3B47EC for ; Tue, 9 Jun 2026 16:21:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.181 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781022094; cv=none; b=Ck0mEn4NlrICow4k/Fz39gMInzXgkqEapmIT1vh07l+nSYSJ/1+NN9Xz+KOOOMVHeLDtjToWPAKfqtDCaDf8afvcY8c8j9Kg04j1cIbVNXh8LR+IQAVvonRJQ3B0Gf459WKKEokpHJ0VLLpFM6cWft+WQ0JTKEB0bhK29vkfexg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1781022094; c=relaxed/simple; bh=ck+WKCWpzacqctEB7DtAb1BlHqEq2My9/KWEZvH7PVI=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=Vyoy6xZ8QpXOOkAWQqcfDlyCPnn6u57qfKqtVpv+BnhbKsXVVQi3lHf7NtFBCIzgGsO6Tgc7tnvLnV4qQEOgxenJni0ZWynE0FJQVEmeoJJ2pD/f/f+cIl+4mhAoYEiQb0bxA/vh6KBJsxCNshrpTAIuYZkXEEPpVPXBPDSAv0s= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=nMsFDVsc; arc=none smtp.client-ip=209.85.214.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="nMsFDVsc" Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-2bf77d4a4e2so35976945ad.1 for ; Tue, 09 Jun 2026 09:21:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1781022092; x=1781626892; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=hUkosP9gtBfCsOOX+JW45J6OLqM+uaRONOFyKMC8tmc=; b=nMsFDVscdOPC/cCGHBwpKFmGVpRtv15z0n4gHPqC57apiWsTdyANk3JxMPvAeY6k4L uWKPUr4ZBSyozWR9Ma3FXNmu02XqXMlSLyWv9OOkxEd/wVKqX5RGK3Jfe9Yfo68dPkq7 3ZK2Y90LNEt1whF8Myqt18hwGdNfqtwwDIpNus/mRK8sdHmbzIJwkBsQQjBHJIZXJEej 7kC+Gfo9HCh5lGP0EZI7FwUvHXtSQFIiw9YQqBQ5Ut9K7Vd0+OBRXdD14zBTApYAz2nA ZSEmKiwlufp7y0CB+XcG5FHPltOMTLIRD99mTubvLKvhvdmD0xYv62LsMarF7Se34UH1 RTNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1781022092; x=1781626892; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=hUkosP9gtBfCsOOX+JW45J6OLqM+uaRONOFyKMC8tmc=; b=nDT6UlTV8LYqN0oYM9mFKRbzKRgpOyx1/P2qV8Rqggnkb+OTRV6sXxAECHwNKw49+L vG9qSLXVkncDY3n9wTzN67k++M6UrwVEXdgKndHazpdR+vlbhFAeuSJI2LxsD6Q6S1oG lcEOLEcoHKhS2r+8irGpRLMpf12zt5XvGygQPOtwgJYD9npvOd4JGdEn5U/CibWhR1LK h5FBWfsfY8IBe7zUIvEVMBHzUconNUu+YuL0Wc6IXYvFqsHULwm5shi7FfYaKOSEOYhc t8ETGeO84j4LFSi3kZhDu6j/vfGwCS5lviIHvnOx4wwd9lWqCrniMF+BLpIcyB4PmqH+ srFw== X-Forwarded-Encrypted: i=1; AFNElJ/DKorHhN2/qg6C9B4DV8lW0zAXh+jGGSYO36Tj2xzoyrAzPJcama1e465HLzIk18KfTSnf6WkT2tQ3xmk=@vger.kernel.org X-Gm-Message-State: AOJu0YwWnYgyozvP1rGSlFmlNMjRhoetHpdV3RsAn/rioFmZBKnkOtHp NHOa1LAdcJRekk71lnZpoQQJuqAhuZo6rWGXedROtLd5nTZO6KhoTcix X-Gm-Gg: Acq92OGh0iBHKzqzrsrAZ0fsA3REsSp9ADHK/Y4TIhYovGadgz+SrimFrQCXrUFdGav oY3Z0OeRHK83xk77gu/KN+gfClF11wQGjfVr4JjKZTeh6dZC6j204O/B24OGdxuFXobse24dYpv s7yTi9K7iMvbpwbpJhsAnZb+y9yp75RMRPStEkTLz1XlguxIqVTiIWr42tAHps1Gf0dTrJx0ns9 +21Pbmrv2zs7t+jkZ8WSiK52mC+mQoeK7NpfXJBsWOjgpLpuXTbBjzJSosMSzazIyblcROpGPvl BVxjBz+UiR8FJmKLzLI4A9ohfWrjQy95O4P5DVlEIivzTW6tVFVilJbKuvkxXmf7wYqeqmTBsUQ IQy/2ngkPD5CoPhad814HCiHjTT7qMZLaGgeWvBrfaw5VdZYXm8HrtBiwZnZC/YQtpUU/VcgoAi PBniWgJVo9VA2Bh1h6yqaBhOuB7JqpLk372G/hq+oB1CGaoS52l8ZLBLdRJZcKBvbirap1YFsfa 9oZNYlp3qbdOKolnkVLJsE= X-Received: by 2002:a17:903:3b8c:b0:2bf:361e:3edc with SMTP id d9443c01a7336-2c1ec3f61a1mr181204435ad.2.1781022091605; Tue, 09 Jun 2026 09:21:31 -0700 (PDT) Received: from SLSGDTSWING002.tail0ac356.ts.net ([129.126.109.177]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2c1663981basm216519105ad.67.2026.06.09.09.21.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 09 Jun 2026 09:21:31 -0700 (PDT) From: Weiming Shi To: Chas Williams <3chas3@gmail.com>, "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: Simon Horman , linux-atm-general@lists.sourceforge.net, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Xiang Mei , Weiming Shi Subject: [PATCH v2] atm: fix use-after-free in sigd_put_skb() Date: Wed, 10 Jun 2026 00:21:08 +0800 Message-ID: <20260609162107.2865310-2-bestswngs@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit sigd_put_skb() delivers a signalling message to the daemon socket named by the global @sigd pointer, ending in a call to sk_data_ready(). It reads @sigd with no synchronisation, so it can race with a close of the daemon socket: sigd_close() clears @sigd and the socket is then torn down and freed. Holding a reference on the socket is not enough to make this safe. The daemon fd close runs __sock_release(), which frees the struct socket -- and the wait queue that sk->sk_wq points at -- via iput() once ->release() has returned. sk_data_ready() (sock_def_readable()) then dereferences a freed sk_wq: KASAN: null-ptr-deref in range [0x0000000000000188-0x000000000000018f] RIP: 0010:sigd_put_skb (net/atm/signaling.c:65) sigd_enq2 (net/atm/signaling.c:228) sigd_enq (net/atm/signaling.c:237) svc_bind (net/atm/svc.c:135) __sys_bind __x64_sys_bind do_syscall_64 Fix it on both sides. sigd_close() now calls sock_orphan(), which under sk_callback_lock sets SOCK_DEAD and clears sk_wq before the socket is freed. sigd_put_skb() latches @sigd with READ_ONCE(), pins the socket with find_get_vcc(), and then takes sk_callback_lock; it delivers only while the socket is still the signalling daemon and not yet SOCK_DEAD, otherwise it drops the skb. sk_callback_lock is used rather than lock_sock() because sigd_put_skb() can be reached from vcc_sendmsg() -> sigd_send(), which already holds lock_sock() on the daemon socket. The READ_ONCE(sigd) != vcc check also rejects a reused VCC: a caller preempted between latching @sigd and validating it in find_get_vcc() could otherwise match a freed-and-reallocated, live (non-SOCK_DEAD) VCC. This needs a concurrent (privileged) daemon teardown, so it is hardening. Triggering the use-after-free requires CAP_NET_ADMIN and CAP_SYS_RAWIO to attach the daemon. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Xiang Mei Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Weiming Shi --- v2: - Also bail when READ_ONCE(sigd) != vcc, rejecting a reused VCC that a preempted caller could match in find_get_vcc() (hardening, no stable). net/atm/signaling.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 358fbe5e4d1d0..346fb969166e8 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c @@ -54,14 +54,32 @@ static struct atm_vcc *find_get_vcc(struct atm_vcc *vcc) static void sigd_put_skb(struct sk_buff *skb) { - if (!sigd) { + struct atm_vcc *vcc; + struct sock *sk; + + vcc = find_get_vcc(READ_ONCE(sigd)); + if (!vcc) { pr_debug("atmsvc: no signaling daemon\n"); kfree_skb(skb); return; } - atm_force_charge(sigd, skb->truesize); - skb_queue_tail(&sk_atm(sigd)->sk_receive_queue, skb); - sk_atm(sigd)->sk_data_ready(sk_atm(sigd)); + sk = sk_atm(vcc); + + /* Pairs with sock_orphan() in sigd_close(). */ + read_lock_bh(&sk->sk_callback_lock); + /* Bail if torn down, or if the slot was reused by another VCC. */ + if (sock_flag(sk, SOCK_DEAD) || READ_ONCE(sigd) != vcc) { + read_unlock_bh(&sk->sk_callback_lock); + sock_put(sk); + kfree_skb(skb); + return; + } + atm_force_charge(vcc, skb->truesize); + skb_queue_tail(&sk->sk_receive_queue, skb); + sk->sk_data_ready(sk); + read_unlock_bh(&sk->sk_callback_lock); + + sock_put(sk); } static void modify_qos(struct atm_vcc *vcc, struct atmsvc_msg *msg) @@ -257,6 +275,9 @@ static void sigd_close(struct atm_vcc *vcc) pr_err("closing with requests pending\n"); skb_queue_purge(&sk_atm(vcc)->sk_receive_queue); + /* Make a concurrent sigd_put_skb() observe SOCK_DEAD and bail. */ + sock_orphan(sk_atm(vcc)); + read_lock(&vcc_sklist_lock); for (i = 0; i < VCC_HTABLE_SIZE; ++i) { struct hlist_head *head = &vcc_hash[i]; -- 2.43.0