diff options
author | Jens Axboe <axboe@kernel.dk> | 2025-02-19 10:22:24 -0700 |
---|---|---|
committer | Christian Brauner <brauner@kernel.org> | 2025-02-20 10:18:37 +0100 |
commit | 6b47d35d4d9e6a3fc7b456bb7f84aea807df5b11 (patch) | |
tree | 9e7980cbf837221e293c76117b750dc265db879f /fs/eventpoll.c | |
parent | 2014c95afecee3e76ca4a56956a936e23283f05b (diff) |
eventpoll: abstract out parameter sanity checking
Add a helper that checks the validity of the file descriptor and
other parameters passed in to epoll_wait().
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Link: https://lore.kernel.org/r/20250219172552.1565603-2-axboe@kernel.dk
Signed-off-by: Christian Brauner <brauner@kernel.org>
Diffstat (limited to 'fs/eventpoll.c')
-rw-r--r-- | fs/eventpoll.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 7c0980db77b3..565bf451df82 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -2445,6 +2445,27 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, return do_epoll_ctl(epfd, op, fd, &epds, false); } +static int ep_check_params(struct file *file, struct epoll_event __user *evs, + int maxevents) +{ + /* The maximum number of event must be greater than zero */ + if (maxevents <= 0 || maxevents > EP_MAX_EVENTS) + return -EINVAL; + + /* Verify that the area passed by the user is writeable */ + if (!access_ok(evs, maxevents * sizeof(struct epoll_event))) + return -EFAULT; + + /* + * We have to check that the file structure underneath the fd + * the user passed to us _is_ an eventpoll file. + */ + if (!is_file_epoll(file)) + return -EINVAL; + + return 0; +} + /* * Implement the event wait interface for the eventpoll file. It is the kernel * part of the user space epoll_wait(2). @@ -2453,26 +2474,16 @@ static int do_epoll_wait(int epfd, struct epoll_event __user *events, int maxevents, struct timespec64 *to) { struct eventpoll *ep; - - /* The maximum number of event must be greater than zero */ - if (maxevents <= 0 || maxevents > EP_MAX_EVENTS) - return -EINVAL; - - /* Verify that the area passed by the user is writeable */ - if (!access_ok(events, maxevents * sizeof(struct epoll_event))) - return -EFAULT; + int ret; /* Get the "struct file *" for the eventpoll file */ CLASS(fd, f)(epfd); if (fd_empty(f)) return -EBADF; - /* - * We have to check that the file structure underneath the fd - * the user passed to us _is_ an eventpoll file. - */ - if (!is_file_epoll(fd_file(f))) - return -EINVAL; + ret = ep_check_params(fd_file(f), events, maxevents); + if (unlikely(ret)) + return ret; /* * At this point it is safe to assume that the "private_data" contains |