]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
io_uring/net: punt IORING_OP_BIND async if it needs file create
authorJens Axboe <axboe@kernel.dk>
Fri, 15 May 2026 16:19:09 +0000 (10:19 -0600)
committerJens Axboe <axboe@kernel.dk>
Fri, 15 May 2026 17:02:16 +0000 (11:02 -0600)
For two reasons:

1) An opcode cannot block inside io_uring_enter() doing submissions, as
   it'll stall the submission side pipeline.

2) Ending up in sb_start_write() -> __sb_start_write() ->
   percpu_down_read_freezable() introduces a new lockdep edge, which it
   correctly complains about.

Check if the socket type is AF_UNIX and has a non-empty pathname. If it
does, mark it REQ_F_FORCE_ASYNC to punt the submission to io-wq rather
than attempt to do it inline.

Fixes: 7481fd93fa0a ("io_uring: Introduce IORING_OP_BIND")
Reviewed-by: Gabriel Krisman Bertazi <krisman@suse.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
io_uring/net.c

index 30cd22c0b934b97ce6e265756b24daca7d398361..8df15b6393587e4ccbe4aae08af5c065bf871560 100644 (file)
@@ -4,6 +4,7 @@
 #include <linux/file.h>
 #include <linux/slab.h>
 #include <linux/net.h>
+#include <linux/un.h>
 #include <linux/compat.h>
 #include <net/compat.h>
 #include <linux/io_uring.h>
@@ -1799,11 +1800,29 @@ out:
        return IOU_COMPLETE;
 }
 
+/*
+ * Check if bind request would potentially end up with filename_create(),
+ * which in turn end up in mnt_want_write() which will grab the fs
+ * percpu start write sem. This can trigger a lockdep warning.
+ */
+static int io_bind_file_create(const struct io_async_msghdr *io, int addr_len)
+{
+       const struct sockaddr_un *sun;
+
+       if (io->addr.ss_family != AF_UNIX)
+               return 0;
+       if (addr_len <= offsetof(struct sockaddr_un, sun_path))
+               return 0;
+       sun = (const struct sockaddr_un *) &io->addr;
+       return sun->sun_path[0] != '\0';
+}
+
 int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_bind *bind = io_kiocb_to_cmd(req, struct io_bind);
        struct sockaddr __user *uaddr;
        struct io_async_msghdr *io;
+       int ret;
 
        if (sqe->len || sqe->buf_index || sqe->rw_flags || sqe->splice_fd_in)
                return -EINVAL;
@@ -1814,7 +1833,12 @@ int io_bind_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        io = io_msg_alloc_async(req);
        if (unlikely(!io))
                return -ENOMEM;
-       return move_addr_to_kernel(uaddr, bind->addr_len, &io->addr);
+       ret = move_addr_to_kernel(uaddr, bind->addr_len, &io->addr);
+       if (unlikely(ret))
+               return ret;
+       if (io_bind_file_create(io, bind->addr_len))
+               req->flags |= REQ_F_FORCE_ASYNC;
+       return 0;
 }
 
 int io_bind(struct io_kiocb *req, unsigned int issue_flags)