Move the logic that copies an epoll_event from user to its own function and expose it in the eventpoll.h header. This allows other subsystems such as io_uring to handle epoll_events.
Signed-off-by: Tudor Cretu tudor.cretu@arm.com --- fs/eventpoll.c | 38 +++++++++++++++++++++++++------------- include/linux/eventpoll.h | 4 ++++ 2 files changed, 29 insertions(+), 13 deletions(-)
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 7e33a2781dec8..c6afc25b1d4ee 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -2197,6 +2197,27 @@ int do_epoll_ctl(int epfd, int op, int fd, struct epoll_event *epds, return error; }
+static int get_compat_epoll_event(struct epoll_event *epds, + const void __user *user_epds) +{ + struct compat_epoll_event compat_epds; + + if (unlikely(copy_from_user(&compat_epds, user_epds, sizeof(compat_epds)))) + return -EFAULT; + epds->events = compat_epds.events; + epds->data = (__kernel_uintptr_t)as_user_ptr(compat_epds.data); + return 0; +} + +int copy_epoll_event_from_user(struct epoll_event *epds, + const void __user *user_epds, + bool compat) +{ + if (compat) + return get_compat_epoll_event(epds, user_epds); + return copy_from_user_with_ptr(epds, user_epds, sizeof(*epds)); +} + /* * The following function implements the controller interface for * the eventpoll file that enables the insertion/removal/change of @@ -2211,20 +2232,11 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event epds;
if (ep_op_has_event(op)) { - if (in_compat_syscall()) { - struct compat_epoll_event compat_epds; - - if (copy_from_user(&compat_epds, event, - sizeof(struct compat_epoll_event))) - return -EFAULT; + int ret;
- epds.events = compat_epds.events; - epds.data = (__kernel_uintptr_t)as_user_ptr(compat_epds.data); - } else { - if (copy_from_user_with_ptr(&epds, event, - sizeof(struct epoll_event))) - return -EFAULT; - } + ret = copy_epoll_event_from_user(&epds, event, in_compat_syscall()); + if (ret) + return -EFAULT; }
return do_epoll_ctl(epfd, op, fd, &epds, false); diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h index 457811d82ff20..62b0829354a0e 100644 --- a/include/linux/eventpoll.h +++ b/include/linux/eventpoll.h @@ -103,4 +103,8 @@ epoll_put_uevent(__poll_t revents, __kernel_uintptr_t data, } #endif
+int copy_epoll_event_from_user(struct epoll_event *epds, + const void __user *user_epds, + bool compat); + #endif /* #ifndef _LINUX_EVENTPOLL_H */