switch epoll_ctl() to fdget

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Issue: SEC-2677
Change-Id: I6e4c67f1121f6ede7138a6d8a3686ebac53d88a3
(cherry picked from commit 7e3fb5842e2294a09fb67c41d8e3f32db5134c43)
This commit is contained in:
Al Viro
2021-10-10 23:46:48 +02:00
committed by Francescodario Cuzzocrea
parent e1b124fb2e
commit 41f9967c1f
+16 -17
View File
@@ -1708,7 +1708,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
{
int error;
int did_lock_epmutex = 0;
struct file *file, *tfile;
struct fd f, tf;
struct eventpoll *ep;
struct epitem *epi;
struct epoll_event epds;
@@ -1718,20 +1718,19 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
copy_from_user(&epds, event, sizeof(struct epoll_event)))
goto error_return;
/* Get the "struct file *" for the eventpoll file */
error = -EBADF;
file = fget(epfd);
if (!file)
f = fdget(epfd);
if (!f.file)
goto error_return;
/* Get the "struct file *" for the target file */
tfile = fget(fd);
if (!tfile)
tf = fdget(fd);
if (!tf.file)
goto error_fput;
/* The target file descriptor must support poll */
error = -EPERM;
if (!tfile->f_op || !tfile->f_op->poll)
if (!tf.file->f_op || !tf.file->f_op->poll)
goto error_tgt_fput;
/* Check if EPOLLWAKEUP is allowed */
@@ -1744,14 +1743,14 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
* adding an epoll file descriptor inside itself.
*/
error = -EINVAL;
if (file == tfile || !is_file_epoll(file))
if (f.file == tf.file || !is_file_epoll(f.file))
goto error_tgt_fput;
/*
* At this point it is safe to assume that the "private_data" contains
* our own data structure.
*/
ep = file->private_data;
ep = f.file->private_data;
/*
* When we insert an epoll file descriptor, inside another epoll file
@@ -1770,15 +1769,15 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
did_lock_epmutex = 1;
}
if (op == EPOLL_CTL_ADD) {
if (is_file_epoll(tfile)) {
if (is_file_epoll(tf.file)) {
error = -ELOOP;
if (ep_loop_check(ep, tfile) != 0) {
if (ep_loop_check(ep, tf.file) != 0) {
clear_tfile_check_list();
goto error_tgt_fput;
}
} else {
get_file(tfile);
list_add(&tfile->f_tfile_llink, &tfile_check_list);
get_file(tf.file);
list_add(&tf.file->f_tfile_llink, &tfile_check_list);
}
}
@@ -1789,14 +1788,14 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
* above, we can be sure to be able to use the item looked up by
* ep_find() till we release the mutex.
*/
epi = ep_find(ep, tfile, fd);
epi = ep_find(ep, tf.file, fd);
error = -EINVAL;
switch (op) {
case EPOLL_CTL_ADD:
if (!epi) {
epds.events |= POLLERR | POLLHUP;
error = ep_insert(ep, &epds, tfile, fd);
error = ep_insert(ep, &epds, tf.file, fd);
} else
error = -EEXIST;
clear_tfile_check_list();
@@ -1821,9 +1820,9 @@ error_tgt_fput:
if (did_lock_epmutex)
mutex_unlock(&epmutex);
fput(tfile);
fdput(tf);
error_fput:
fput(file);
fdput(f);
error_return:
return error;