|
@@ -105,6 +105,8 @@
|
|
|
/* Maximum msec timeout value storeable in a long int */
|
|
|
#define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ)
|
|
|
|
|
|
+#define EP_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
|
|
|
+
|
|
|
|
|
|
struct epoll_filefd {
|
|
|
struct file *file;
|
|
@@ -497,7 +499,7 @@ void eventpoll_release_file(struct file *file)
|
|
|
*/
|
|
|
asmlinkage long sys_epoll_create(int size)
|
|
|
{
|
|
|
- int error, fd;
|
|
|
+ int error, fd = -1;
|
|
|
struct eventpoll *ep;
|
|
|
struct inode *inode;
|
|
|
struct file *file;
|
|
@@ -640,7 +642,6 @@ eexit_1:
|
|
|
return error;
|
|
|
}
|
|
|
|
|
|
-#define MAX_EVENTS (INT_MAX / sizeof(struct epoll_event))
|
|
|
|
|
|
/*
|
|
|
* Implement the event wait interface for the eventpoll file. It is the kernel
|
|
@@ -657,7 +658,7 @@ asmlinkage long sys_epoll_wait(int epfd, struct epoll_event __user *events,
|
|
|
current, epfd, events, maxevents, timeout));
|
|
|
|
|
|
/* The maximum number of event must be greater than zero */
|
|
|
- if (maxevents <= 0 || maxevents > MAX_EVENTS)
|
|
|
+ if (maxevents <= 0 || maxevents > EP_MAX_EVENTS)
|
|
|
return -EINVAL;
|
|
|
|
|
|
/* Verify that the area passed by the user is writeable */
|
|
@@ -699,6 +700,55 @@ eexit_1:
|
|
|
}
|
|
|
|
|
|
|
|
|
+#ifdef TIF_RESTORE_SIGMASK
|
|
|
+
|
|
|
+/*
|
|
|
+ * Implement the event wait interface for the eventpoll file. It is the kernel
|
|
|
+ * part of the user space epoll_pwait(2).
|
|
|
+ */
|
|
|
+asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events,
|
|
|
+ int maxevents, int timeout, const sigset_t __user *sigmask,
|
|
|
+ size_t sigsetsize)
|
|
|
+{
|
|
|
+ int error;
|
|
|
+ sigset_t ksigmask, sigsaved;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If the caller wants a certain signal mask to be set during the wait,
|
|
|
+ * we apply it here.
|
|
|
+ */
|
|
|
+ if (sigmask) {
|
|
|
+ if (sigsetsize != sizeof(sigset_t))
|
|
|
+ return -EINVAL;
|
|
|
+ if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
|
|
|
+ return -EFAULT;
|
|
|
+ sigdelsetmask(&ksigmask, sigmask(SIGKILL) | sigmask(SIGSTOP));
|
|
|
+ sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
|
|
|
+ }
|
|
|
+
|
|
|
+ error = sys_epoll_wait(epfd, events, maxevents, timeout);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * If we changed the signal mask, we need to restore the original one.
|
|
|
+ * In case we've got a signal while waiting, we do not restore the
|
|
|
+ * signal mask yet, and we allow do_signal() to deliver the signal on
|
|
|
+ * the way back to userspace, before the signal mask is restored.
|
|
|
+ */
|
|
|
+ if (sigmask) {
|
|
|
+ if (error == -EINTR) {
|
|
|
+ memcpy(¤t->saved_sigmask, &sigsaved,
|
|
|
+ sizeof(sigsaved));
|
|
|
+ set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
|
+ } else
|
|
|
+ sigprocmask(SIG_SETMASK, &sigsaved, NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
+#endif /* #ifdef TIF_RESTORE_SIGMASK */
|
|
|
+
|
|
|
+
|
|
|
/*
|
|
|
* Creates the file descriptor to be used by the epoll interface.
|
|
|
*/
|