net: add accept helper not installing fd
authorPavel Begunkov <asml.silence@gmail.com>
Wed, 25 Aug 2021 11:25:44 +0000 (12:25 +0100)
committerJens Axboe <axboe@kernel.dk>
Wed, 25 Aug 2021 12:36:56 +0000 (06:36 -0600)
Introduce and reuse a helper that acts similarly to __sys_accept4_file()
but returns struct file instead of installing file descriptor. Will be
used by io_uring.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Acked-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Acked-by: David S. Miller <davem@davemloft.net>
Link: https://lore.kernel.org/r/c57b9e8e818d93683a3d24f8ca50ca038d1da8c4.1629888991.git.asml.silence@gmail.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>
include/linux/socket.h
net/socket.c

index 0d8e3dc..d3c1a42 100644 (file)
@@ -421,6 +421,9 @@ extern int __sys_accept4_file(struct file *file, unsigned file_flags,
                        struct sockaddr __user *upeer_sockaddr,
                         int __user *upeer_addrlen, int flags,
                         unsigned long nofile);
+extern struct file *do_accept(struct file *file, unsigned file_flags,
+                             struct sockaddr __user *upeer_sockaddr,
+                             int __user *upeer_addrlen, int flags);
 extern int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
                         int __user *upeer_addrlen, int flags);
 extern int __sys_socket(int family, int type, int protocol);
index 0b2dad3..532fff5 100644 (file)
@@ -1722,32 +1722,22 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)
        return __sys_listen(fd, backlog);
 }
 
-int __sys_accept4_file(struct file *file, unsigned file_flags,
+struct file *do_accept(struct file *file, unsigned file_flags,
                       struct sockaddr __user *upeer_sockaddr,
-                      int __user *upeer_addrlen, int flags,
-                      unsigned long nofile)
+                      int __user *upeer_addrlen, int flags)
 {
        struct socket *sock, *newsock;
        struct file *newfile;
-       int err, len, newfd;
+       int err, len;
        struct sockaddr_storage address;
 
-       if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
-               return -EINVAL;
-
-       if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
-               flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
-
        sock = sock_from_file(file);
-       if (!sock) {
-               err = -ENOTSOCK;
-               goto out;
-       }
+       if (!sock)
+               return ERR_PTR(-ENOTSOCK);
 
-       err = -ENFILE;
        newsock = sock_alloc();
        if (!newsock)
-               goto out;
+               return ERR_PTR(-ENFILE);
 
        newsock->type = sock->type;
        newsock->ops = sock->ops;
@@ -1758,18 +1748,9 @@ int __sys_accept4_file(struct file *file, unsigned file_flags,
         */
        __module_get(newsock->ops->owner);
 
-       newfd = __get_unused_fd_flags(flags, nofile);
-       if (unlikely(newfd < 0)) {
-               err = newfd;
-               sock_release(newsock);
-               goto out;
-       }
        newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name);
-       if (IS_ERR(newfile)) {
-               err = PTR_ERR(newfile);
-               put_unused_fd(newfd);
-               goto out;
-       }
+       if (IS_ERR(newfile))
+               return newfile;
 
        err = security_socket_accept(sock, newsock);
        if (err)
@@ -1794,16 +1775,38 @@ int __sys_accept4_file(struct file *file, unsigned file_flags,
        }
 
        /* File flags are not inherited via accept() unlike another OSes. */
-
-       fd_install(newfd, newfile);
-       err = newfd;
-out:
-       return err;
+       return newfile;
 out_fd:
        fput(newfile);
-       put_unused_fd(newfd);
-       goto out;
+       return ERR_PTR(err);
+}
+
+int __sys_accept4_file(struct file *file, unsigned file_flags,
+                      struct sockaddr __user *upeer_sockaddr,
+                      int __user *upeer_addrlen, int flags,
+                      unsigned long nofile)
+{
+       struct file *newfile;
+       int newfd;
 
+       if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
+               return -EINVAL;
+
+       if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
+               flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
+
+       newfd = __get_unused_fd_flags(flags, nofile);
+       if (unlikely(newfd < 0))
+               return newfd;
+
+       newfile = do_accept(file, file_flags, upeer_sockaddr, upeer_addrlen,
+                           flags);
+       if (IS_ERR(newfile)) {
+               put_unused_fd(newfd);
+               return PTR_ERR(newfile);
+       }
+       fd_install(newfd, newfile);
+       return newfd;
 }
 
 /*