Skip to content

Commit 4022e7a

Browse files
committed
io_uring: make sure openat/openat2 honor rlimit nofile
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 <[email protected]> Tested-by: Dmitry Kadashev <[email protected]> Acked-by: David S. Miller <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent f1d96a8 commit 4022e7a

File tree

3 files changed

+11
-2
lines changed

3 files changed

+11
-2
lines changed

fs/file.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,9 +540,14 @@ static int alloc_fd(unsigned start, unsigned flags)
540540
return __alloc_fd(current->files, start, rlimit(RLIMIT_NOFILE), flags);
541541
}
542542

543+
int __get_unused_fd_flags(unsigned flags, unsigned long nofile)
544+
{
545+
return __alloc_fd(current->files, 0, nofile, flags);
546+
}
547+
543548
int get_unused_fd_flags(unsigned flags)
544549
{
545-
return __alloc_fd(current->files, 0, rlimit(RLIMIT_NOFILE), flags);
550+
return __get_unused_fd_flags(flags, rlimit(RLIMIT_NOFILE));
546551
}
547552
EXPORT_SYMBOL(get_unused_fd_flags);
548553

fs/io_uring.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ struct io_open {
397397
struct filename *filename;
398398
struct statx __user *buffer;
399399
struct open_how how;
400+
unsigned long nofile;
400401
};
401402

402403
struct io_files_update {
@@ -2577,6 +2578,7 @@ static int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
25772578
return ret;
25782579
}
25792580

2581+
req->open.nofile = rlimit(RLIMIT_NOFILE);
25802582
req->flags |= REQ_F_NEED_CLEANUP;
25812583
return 0;
25822584
}
@@ -2618,6 +2620,7 @@ static int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
26182620
return ret;
26192621
}
26202622

2623+
req->open.nofile = rlimit(RLIMIT_NOFILE);
26212624
req->flags |= REQ_F_NEED_CLEANUP;
26222625
return 0;
26232626
}
@@ -2636,7 +2639,7 @@ static int io_openat2(struct io_kiocb *req, struct io_kiocb **nxt,
26362639
if (ret)
26372640
goto err;
26382641

2639-
ret = get_unused_fd_flags(req->open.how.flags);
2642+
ret = __get_unused_fd_flags(req->open.how.flags, req->open.nofile);
26402643
if (ret < 0)
26412644
goto err;
26422645

include/linux/file.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ extern int f_dupfd(unsigned int from, struct file *file, unsigned flags);
8585
extern int replace_fd(unsigned fd, struct file *file, unsigned flags);
8686
extern void set_close_on_exec(unsigned int fd, int flag);
8787
extern bool get_close_on_exec(unsigned int fd);
88+
extern int __get_unused_fd_flags(unsigned flags, unsigned long nofile);
8889
extern int get_unused_fd_flags(unsigned flags);
8990
extern void put_unused_fd(unsigned int fd);
9091

0 commit comments

Comments
 (0)