Skip to contentSkip to conversation

atm: Fix uninit and mem accounting leak in vcc_sendmsg().

PATCH Applied Kuniyuki Iwashima 2 participants 4 messages Jun 16, 2025 – Jun 18, 2025

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

v2 cover atm: Fix uninit and mem accounting leak in vcc_sendmsg().

From: Kuniyuki Iwashima <[email protected]>

Patch 1 fixes uninit issue reported by KMSAN, and patch 2 fixes another issue found by Simon Horman during review for v1 patch.

Changes:
v2:
* Add patch 2
* Patch 1: reuse "done:" label

v1: https://lore.kernel.org/netdev/[email protected]/

Kuniyuki Iwashima (2):
atm: atmtcp: Free invalid length skb in atmtcp_c_send().
atm: Revert atm_account_tx() if copy_from_iter_full() fails.

 drivers/atm/atmtcp.c   | 4 +++-
 include/linux/atmdev.h | 6 ++++++
 net/atm/common.c       | 1 +
 net/atm/raw.c          | 2 +-
 4 files changed, 11 insertions(+), 2 deletions(-)
Signature · 1 line
2.49.0
#1 lore raw

PATCH v2 1/2 atm: atmtcp: Free invalid length skb in atmtcp_c_send().

From: Kuniyuki Iwashima <[email protected]>

syzbot reported the splat below. [0]

vcc_sendmsg() copies data passed from userspace to skb and passes it to vcc->dev->ops->send().

atmtcp_c_send() accesses skb->data as struct atmtcp_hdr after checking if skb->len is 0, but it's not enough.

Also, when skb->len == 0, skb and sk (vcc) were leaked because dev_kfree_skb() is not called and sk_wmem_alloc adjustment is missing to revert atm_account_tx() in vcc_sendmsg(), which is expected to be done in atm_pop_raw().

Let's properly free skb with an invalid length in atmtcp_c_send().

[0]:

BUG: KMSAN: uninit-value in atmtcp_c_send+0x255/0xed0 drivers/atm/atmtcp.c:294
 atmtcp_c_send+0x255/0xed0 drivers/atm/atmtcp.c:294
 vcc_sendmsg+0xd7c/0xff0 net/atm/common.c:644
 sock_sendmsg_nosec net/socket.c:712 [inline]
 __sock_sendmsg+0x330/0x3d0 net/socket.c:727
 ____sys_sendmsg+0x7e0/0xd80 net/socket.c:2566
 ___sys_sendmsg+0x271/0x3b0 net/socket.c:2620
 __sys_sendmsg net/socket.c:2652 [inline]
 __do_sys_sendmsg net/socket.c:2657 [inline]
 __se_sys_sendmsg net/socket.c:2655 [inline]
 __x64_sys_sendmsg+0x211/0x3e0 net/socket.c:2655
 x64_sys_call+0x32fb/0x3db0 arch/x86/include/generated/asm/syscalls_64.h:47
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Uninit was created at:

 slab_post_alloc_hook mm/slub.c:4154 [inline]
 slab_alloc_node mm/slub.c:4197 [inline]
 kmem_cache_alloc_node_noprof+0x818/0xf00 mm/slub.c:4249
 kmalloc_reserve+0x13c/0x4b0 net/core/skbuff.c:579
 __alloc_skb+0x347/0x7d0 net/core/skbuff.c:670
 alloc_skb include/linux/skbuff.h:1336 [inline]
 vcc_sendmsg+0xb40/0xff0 net/atm/common.c:628
 sock_sendmsg_nosec net/socket.c:712 [inline]
 __sock_sendmsg+0x330/0x3d0 net/socket.c:727
 ____sys_sendmsg+0x7e0/0xd80 net/socket.c:2566
 ___sys_sendmsg+0x271/0x3b0 net/socket.c:2620
 __sys_sendmsg net/socket.c:2652 [inline]
 __do_sys_sendmsg net/socket.c:2657 [inline]
 __se_sys_sendmsg net/socket.c:2655 [inline]
 __x64_sys_sendmsg+0x211/0x3e0 net/socket.c:2655
 x64_sys_call+0x32fb/0x3db0 arch/x86/include/generated/asm/syscalls_64.h:47
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xd9/0x210 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

CPU: 1 UID: 0 PID: 5798 Comm: syz-executor192 Not tainted 6.16.0-rc1-syzkaller-00010-g2c4a1f3fe03e #0 PREEMPT(undef)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025

---
v2: Reuse done: label

---
 drivers/atm/atmtcp.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/atm/atmtcp.c +3 -1
index d4aa0f353b6c..eeae160c898d 100644
@@ -288,7 +288,9 @@ static int atmtcp_c_send(struct atm_vcc *vcc,struct sk_buff *skb)
 	struct sk_buff *new_skb;
 	int result = 0;
 
-	if (!skb->len) return 0;
+	if (skb->len < sizeof(struct atmtcp_hdr))
+		goto done;
+
 	dev = vcc->dev_data;
 	hdr = (struct atmtcp_hdr *) skb->data;
 	if (hdr->length == ATMTCP_HDR_MAGIC) {
Signature · 1 line
2.49.0
#2 lore raw

PATCH v2 2/2 atm: Revert atm_account_tx() if copy_from_iter_full() fails.

In reply to Kuniyuki Iwashima

From: Kuniyuki Iwashima <[email protected]>

In vcc_sendmsg(), we account skb->truesize to sk->sk_wmem_alloc by atm_account_tx().

It is expected to be reverted by atm_pop_raw() later called by vcc->dev->ops->send(vcc, skb).

However, vcc_sendmsg() misses the same revert when copy_from_iter_full() fails, and then we will leak a socket.

Let's factorise the revert part as atm_return_tx() and call it in the failure path.

Note that the corresponding sk_wmem_alloc operation can be found in alloc_tx() as of the blamed commit.

  $ git blame -L:alloc_tx net/atm/common.c c55fa3cccbc2c~
---
 include/linux/atmdev.h | 6 ++++++
 net/atm/common.c       | 1 +
 net/atm/raw.c          | 2 +-
 3 files changed, 8 insertions(+), 1 deletion(-)
include/linux/atmdev.h +6 -0
index 9b02961d65ee..45f2f278b50a 100644
@@ -249,6 +249,12 @@ static inline void atm_account_tx(struct atm_vcc *vcc, struct sk_buff *skb)
 	ATM_SKB(skb)->atm_options = vcc->atm_options;
 }
 
+static inline void atm_return_tx(struct atm_vcc *vcc, struct sk_buff *skb)
+{
+	WARN_ON_ONCE(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize,
+					   &sk_atm(vcc)->sk_wmem_alloc));
+}
+
 static inline void atm_force_charge(struct atm_vcc *vcc,int truesize)
 {
 	atomic_add(truesize, &sk_atm(vcc)->sk_rmem_alloc);
net/atm/common.c +1 -0
index 9b75699992ff..d7f7976ea13a 100644
@@ -635,6 +635,7 @@ int vcc_sendmsg(struct socket *sock, struct msghdr *m, size_t size)
 
 	skb->dev = NULL; /* for paths shared with net_device interfaces */
 	if (!copy_from_iter_full(skb_put(skb, size), size, &m->msg_iter)) {
+		atm_return_tx(vcc, skb);
 		kfree_skb(skb);
 		error = -EFAULT;
 		goto out;
net/atm/raw.c +1 -1
index 2b5f78a7ec3e..1e6511ec842c 100644
@@ -36,7 +36,7 @@ static void atm_pop_raw(struct atm_vcc *vcc, struct sk_buff *skb)
 
 	pr_debug("(%d) %d -= %d\n",
 		 vcc->vci, sk_wmem_alloc_get(sk), ATM_SKB(skb)->acct_truesize);
-	WARN_ON(refcount_sub_and_test(ATM_SKB(skb)->acct_truesize, &sk->sk_wmem_alloc));
+	atm_return_tx(vcc, skb);
 	dev_kfree_skb_any(skb);
 	sk->sk_write_space(sk);
 }
Signature · 1 line
2.49.0
#3 lore raw
In reply to Kuniyuki Iwashima
This series was applied to netdev/net.git (main) by Jakub Kicinski <[email protected]>:

Hello:

This series was applied to netdev/net.git (main)
by Jakub Kicinski <[email protected]>:

Quoted 6 lines · On Mon, 16 Jun 2025 11:21:13 -0700 you wrote:

From: Kuniyuki Iwashima <[email protected]>

Patch 1 fixes uninit issue reported by KMSAN, and patch 2 fixes another issue found by Simon Horman during review for v1 patch.

Quoted 6 lines

Changes:
v2:
* Add patch 2
* Patch 1: reuse "done:" label

[...]

Here is the summary with links:
- [v2,net,1/2] atm: atmtcp: Free invalid length skb in atmtcp_c_send().

    https://git.kernel.org/netdev/net/c/2f370ae1fb63
  - [v2,net,2/2] atm: Revert atm_account_tx() if copy_from_iter_full() fails.
    https://git.kernel.org/netdev/net/c/7851263998d4

You are awesome, thank you!

Signature · 2 lines
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html