Index: sys/compat/linux/linux_event.c =================================================================== --- sys/compat/linux/linux_event.c +++ sys/compat/linux/linux_event.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -443,6 +444,27 @@ return (0); } +static bool +linux_fd_is_epollable(struct thread *td, int fd) +{ + struct file *fp; + int error; + bool epollable; + + error = fget(td, fd, &cap_no_rights, &fp); + if (error != 0) + return (true); + + if (fp->f_type == DTYPE_VNODE && + (fp->f_vnode->v_type == VREG || fp->f_vnode->v_type == VDIR)) + epollable = false; + else + epollable = true; + fdrop(fp, td); + + return (epollable); +} + /* * Load epoll filter, convert it to kevent filter * and load it into kevent subsystem. @@ -505,6 +527,10 @@ case LINUX_EPOLL_CTL_ADD: if (epoll_fd_registered(td, epfp, args->fd)) { error = EEXIST; + goto leave0; + } + if (!linux_fd_is_epollable(td, args->fd)) { + error = EPERM; goto leave0; } break;