io_uring: make sure accept honor rlimit nofile
authorJens Axboe <axboe@kernel.dk>
Fri, 20 Mar 2020 02:16:56 +0000 (20:16 -0600)
committerJens Axboe <axboe@kernel.dk>
Fri, 20 Mar 2020 14:48:36 +0000 (08:48 -0600)
Just like commit 4022e7af86be, this fixes the fact that
IORING_OP_ACCEPT ends up using get_unused_fd_flags(), which checks
current->signal->rlim[] for limits.

Add an extra argument to __sys_accept4_file() that allows us to pass
in the proper nofile limit, and grab it at request prep time.

Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
fs/io_uring.c
include/linux/socket.h
net/socket.c

index fe5ded7..3affd96 100644 (file)
@@ -343,6 +343,7 @@ struct io_accept {
        struct sockaddr __user          *addr;
        int __user                      *addr_len;
        int                             flags;
+       unsigned long                   nofile;
 };
 
 struct io_sync {
@@ -3324,6 +3325,7 @@ static int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        accept->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
        accept->addr_len = u64_to_user_ptr(READ_ONCE(sqe->addr2));
        accept->flags = READ_ONCE(sqe->accept_flags);
+       accept->nofile = rlimit(RLIMIT_NOFILE);
        return 0;
 #else
        return -EOPNOTSUPP;
@@ -3340,7 +3342,8 @@ static int __io_accept(struct io_kiocb *req, struct io_kiocb **nxt,
 
        file_flags = force_nonblock ? O_NONBLOCK : 0;
        ret = __sys_accept4_file(req->file, file_flags, accept->addr,
-                                       accept->addr_len, accept->flags);
+                                       accept->addr_len, accept->flags,
+                                       accept->nofile);
        if (ret == -EAGAIN && force_nonblock)
                return -EAGAIN;
        if (ret == -ERESTARTSYS)
index 2d23134..15f3412 100644 (file)
@@ -401,7 +401,8 @@ extern int __sys_sendto(int fd, void __user *buff, size_t len,
                        int addr_len);
 extern int __sys_accept4_file(struct file *file, unsigned file_flags,
                        struct sockaddr __user *upeer_sockaddr,
-                        int __user *upeer_addrlen, int flags);
+                        int __user *upeer_addrlen, int flags,
+                        unsigned long nofile);
 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 b79a05d..2eecf15 100644 (file)
@@ -1707,7 +1707,8 @@ SYSCALL_DEFINE2(listen, int, fd, int, backlog)
 
 int __sys_accept4_file(struct file *file, unsigned file_flags,
                       struct sockaddr __user *upeer_sockaddr,
-                      int __user *upeer_addrlen, int flags)
+                      int __user *upeer_addrlen, int flags,
+                      unsigned long nofile)
 {
        struct socket *sock, *newsock;
        struct file *newfile;
@@ -1738,7 +1739,7 @@ int __sys_accept4_file(struct file *file, unsigned file_flags,
         */
        __module_get(newsock->ops->owner);
 
-       newfd = get_unused_fd_flags(flags);
+       newfd = __get_unused_fd_flags(flags, nofile);
        if (unlikely(newfd < 0)) {
                err = newfd;
                sock_release(newsock);
@@ -1807,7 +1808,8 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
        f = fdget(fd);
        if (f.file) {
                ret = __sys_accept4_file(f.file, 0, upeer_sockaddr,
-                                               upeer_addrlen, flags);
+                                               upeer_addrlen, flags,
+                                               rlimit(RLIMIT_NOFILE));
                if (f.flags)
                        fput(f.file);
        }