From ee1972def665f4ea965bd654925711261a9ad241 Mon Sep 17 00:00:00 2001 From: Willem de Bruijn Date: Sun, 27 Sep 2026 22:03:29 -0400 Subject: [PATCH] net: downgrade BUG_ON EIOCBQUEUED in sock_sendmsg_nosec sock_sendmsg_nosec() runs in syscall context but calls BUG_ON() if proto_ops->sendmsg() returns -EIOCBQUEUED. Crashing the kernel on an unexpected return value is dangerous for production workloads. This risk is real: any signed integer overflow in a sendmsg handler that returns 0xfffffdef (-529, -EIOCBQUEUED) triggers this BUG_ON. In one month, two such bugs were reported in PF_PACKET, reachable by a local user with CAP_NET_RAW in a user namespace: - Commit 73e594c19b4f ("af_packet: Don't cast tpacket_hdr.tp_len to int in tpacket_parse_header().") - In review ("net/packet: prevent TX_RING byte count overflow") https://lore.kernel.org/netdev/20260925124829.6595-1-ilkka.lappetelainen@gmail.com/ Replace the BUG_ON with DEBUG_NET_WARN_ON_ONCE() to retain debug and syzbot coverage, and return -EIO so that -EIOCBQUEUED does not leak to userspace or trigger the BUG_ON(ret == -EIOCBQUEUED) in VFS callers of sock_write_iter() such as new_sync_write(). Failing gracefully is safe because the original reason for the BUG_ON is gone. It was added in commit 599bd19bdc4c ("fs: don't allow to complete sync iocbs through aio_complete") and commit d8725c86aeba ("get rid of the size argument of sock_sendmsg()") to prevent an async completion from corrupting a caller's on-stack kiocb. Commit 1b784140474e ("net: Remove iocb argument from sendmsg and recvmsg") removed that on-stack kiocb. More recently commit fcc77d33a34c ("net: Remove support for AIO on sockets") removed socket AIO support entirely. Signed-off-by: Willem de Bruijn Link: https://patch.msgid.link/20260928020420.3097018-1-willemdebruijn.kernel@gmail.com Signed-off-by: Paolo Abeni --- net/socket.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/socket.c b/net/socket.c index bb0e1e118ef6..d7a2d2195a07 100644 --- a/net/socket.c +++ b/net/socket.c @@ -800,7 +800,10 @@ static inline int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg) int ret = INDIRECT_CALL_INET(READ_ONCE(sock->ops)->sendmsg, inet6_sendmsg, inet_sendmsg, sock, msg, msg_data_left(msg)); - BUG_ON(ret == -EIOCBQUEUED); + if (unlikely(ret == -EIOCBQUEUED)) { + DEBUG_NET_WARN_ON_ONCE(1); + ret = -EIO; + } if (trace_sock_send_length_enabled()) call_trace_sock_send_length(sock->sk, ret, 0);