From 53a82f3191c30c132f25fff7dec4c293201898ad Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 15 Apr 2021 17:37:14 +0800 Subject: [PATCH] io_uring: make sure openat/openat2 honor rlimit nofile mainline inclusion from mainline-5.6-rc7 commit 4022e7af86be2dd62975dedb6b7ea551d108695e category: feature bugzilla: https://bugzilla.openeuler.org/show_bug.cgi?id=27 CVE: NA --------------------------- Dmitry reports that a test case shows that io_uring isn't honoring a modified rlimit nofile setting. get_unused_fd_flags() checks the task signal->rlimi[] for the limits. As this isn't easily inheritable, provide a __get_unused_fd_flags() that takes the value instead. Then we can grab it when the request is prepared (from the original task), and pass that in when we do the async part part of the open. Reported-by: Dmitry Kadashev Tested-by: Dmitry Kadashev Acked-by: David S. Miller Signed-off-by: Jens Axboe Conflicts: fs/io_uring.c [ignore openat2 for commit cebdb98617ae ("io_uring: add support for IORING_OP_OPENAT2") not merged] Signed-off-by: yangerkun Reviewed-by: zhangyi (F) Signed-off-by: Cheng Jian --- fs/file.c | 7 ++++++- fs/io_uring.c | 4 +++- include/linux/file.h | 1 + 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/file.c b/fs/file.c index f78fd5062429..e07d18f8865b 100644 --- a/fs/file.c +++ b/fs/file.c @@ -579,9 +579,14 @@ static int alloc_fd(unsigned start, unsigned flags) return __alloc_fd(current->files, start, rlimit(RLIMIT_NOFILE), flags); } +int __get_unused_fd_flags(unsigned flags, unsigned long nofile) +{ + return __alloc_fd(current->files, 0, nofile, flags); +} + int get_unused_fd_flags(unsigned flags) { - return __alloc_fd(current->files, 0, rlimit(RLIMIT_NOFILE), flags); + return __get_unused_fd_flags(flags, rlimit(RLIMIT_NOFILE)); } EXPORT_SYMBOL(get_unused_fd_flags); diff --git a/fs/io_uring.c b/fs/io_uring.c index ffbf53755ac4..a58c4b78f811 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -398,6 +398,7 @@ struct io_open { struct filename *filename; struct statx __user *buffer; int flags; + unsigned long nofile; }; struct io_files_update { @@ -2571,6 +2572,7 @@ static int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) return ret; } + req->open.nofile = rlimit(RLIMIT_NOFILE); req->flags |= REQ_F_NEED_CLEANUP; return 0; } @@ -2589,7 +2591,7 @@ static int io_openat(struct io_kiocb *req, struct io_kiocb **nxt, if (ret) goto err; - ret = get_unused_fd_flags(req->open.flags); + ret = __get_unused_fd_flags(req->open.flags, req->open.nofile); if (ret < 0) goto err; diff --git a/include/linux/file.h b/include/linux/file.h index 3fcddff56bc4..82fa6064662d 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -83,6 +83,7 @@ extern int f_dupfd(unsigned int from, struct file *file, unsigned flags); extern int replace_fd(unsigned fd, struct file *file, unsigned flags); extern void set_close_on_exec(unsigned int fd, int flag); extern bool get_close_on_exec(unsigned int fd); +extern int __get_unused_fd_flags(unsigned flags, unsigned long nofile); extern int get_unused_fd_flags(unsigned flags); extern void put_unused_fd(unsigned int fd); -- GitLab