Merge tag 'pci-v4.16-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
[sfrench/cifs-2.6.git] / fs / pipe.c
index a449ca0ec0c61fe37a7cef9bf817c570e8324691..7b1954caf3885d1c24458aa3a1843802c0506a09 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
  */
 unsigned int pipe_max_size = 1048576;
 
-/*
- * Minimum pipe size, as required by POSIX
- */
-unsigned int pipe_min_size = PAGE_SIZE;
-
 /* Maximum allocatable pages per user. Hard limit is unset by default, soft
  * matches default values.
  */
@@ -332,7 +327,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
                        break;
                }
                if (do_wakeup) {
-                       wake_up_interruptible_sync_poll(&pipe->wait, POLLOUT | POLLWRNORM);
+                       wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
                        kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
                }
                pipe_wait(pipe);
@@ -341,7 +336,7 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
 
        /* Signal writers asynchronously that there is more room. */
        if (do_wakeup) {
-               wake_up_interruptible_sync_poll(&pipe->wait, POLLOUT | POLLWRNORM);
+               wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
                kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
        }
        if (ret > 0)
@@ -468,7 +463,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
                        break;
                }
                if (do_wakeup) {
-                       wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
+                       wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLRDNORM);
                        kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
                        do_wakeup = 0;
                }
@@ -479,7 +474,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
 out:
        __pipe_unlock(pipe);
        if (do_wakeup) {
-               wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
+               wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLRDNORM);
                kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
        }
        if (ret > 0 && sb_start_write_trylock(file_inode(filp)->i_sb)) {
@@ -528,19 +523,19 @@ pipe_poll(struct file *filp, poll_table *wait)
        nrbufs = pipe->nrbufs;
        mask = 0;
        if (filp->f_mode & FMODE_READ) {
-               mask = (nrbufs > 0) ? POLLIN | POLLRDNORM : 0;
+               mask = (nrbufs > 0) ? EPOLLIN | EPOLLRDNORM : 0;
                if (!pipe->writers && filp->f_version != pipe->w_counter)
-                       mask |= POLLHUP;
+                       mask |= EPOLLHUP;
        }
 
        if (filp->f_mode & FMODE_WRITE) {
-               mask |= (nrbufs < pipe->buffers) ? POLLOUT | POLLWRNORM : 0;
+               mask |= (nrbufs < pipe->buffers) ? EPOLLOUT | EPOLLWRNORM : 0;
                /*
-                * Most Unices do not set POLLERR for FIFOs but on Linux they
+                * Most Unices do not set EPOLLERR for FIFOs but on Linux they
                 * behave exactly like pipes for poll().
                 */
                if (!pipe->readers)
-                       mask |= POLLERR;
+                       mask |= EPOLLERR;
        }
 
        return mask;
@@ -573,7 +568,7 @@ pipe_release(struct inode *inode, struct file *file)
                pipe->writers--;
 
        if (pipe->readers || pipe->writers) {
-               wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM | POLLERR | POLLHUP);
+               wake_up_interruptible_sync_poll(&pipe->wait, EPOLLIN | EPOLLOUT | EPOLLRDNORM | EPOLLWRNORM | EPOLLERR | EPOLLHUP);
                kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
                kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
        }
@@ -610,12 +605,21 @@ static unsigned long account_pipe_buffers(struct user_struct *user,
 
 static bool too_many_pipe_buffers_soft(unsigned long user_bufs)
 {
-       return pipe_user_pages_soft && user_bufs >= pipe_user_pages_soft;
+       unsigned long soft_limit = READ_ONCE(pipe_user_pages_soft);
+
+       return soft_limit && user_bufs > soft_limit;
 }
 
 static bool too_many_pipe_buffers_hard(unsigned long user_bufs)
 {
-       return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard;
+       unsigned long hard_limit = READ_ONCE(pipe_user_pages_hard);
+
+       return hard_limit && user_bufs > hard_limit;
+}
+
+static bool is_unprivileged_user(void)
+{
+       return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
 }
 
 struct pipe_inode_info *alloc_pipe_info(void)
@@ -624,22 +628,23 @@ struct pipe_inode_info *alloc_pipe_info(void)
        unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
        struct user_struct *user = get_current_user();
        unsigned long user_bufs;
+       unsigned int max_size = READ_ONCE(pipe_max_size);
 
        pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT);
        if (pipe == NULL)
                goto out_free_uid;
 
-       if (pipe_bufs * PAGE_SIZE > pipe_max_size && !capable(CAP_SYS_RESOURCE))
-               pipe_bufs = pipe_max_size >> PAGE_SHIFT;
+       if (pipe_bufs * PAGE_SIZE > max_size && !capable(CAP_SYS_RESOURCE))
+               pipe_bufs = max_size >> PAGE_SHIFT;
 
        user_bufs = account_pipe_buffers(user, 0, pipe_bufs);
 
-       if (too_many_pipe_buffers_soft(user_bufs)) {
+       if (too_many_pipe_buffers_soft(user_bufs) && is_unprivileged_user()) {
                user_bufs = account_pipe_buffers(user, pipe_bufs, 1);
                pipe_bufs = 1;
        }
 
-       if (too_many_pipe_buffers_hard(user_bufs))
+       if (too_many_pipe_buffers_hard(user_bufs) && is_unprivileged_user())
                goto out_revert_acct;
 
        pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer),
@@ -931,7 +936,7 @@ static int fifo_open(struct inode *inode, struct file *filp)
 
                if (!is_pipe && !pipe->writers) {
                        if ((filp->f_flags & O_NONBLOCK)) {
-                               /* suppress POLLHUP until we have
+                               /* suppress EPOLLHUP until we have
                                 * seen a writer */
                                filp->f_version = pipe->w_counter;
                        } else {
@@ -1020,18 +1025,16 @@ const struct file_operations pipefifo_fops = {
  * Currently we rely on the pipe array holding a power-of-2 number
  * of pages. Returns 0 on error.
  */
-unsigned int round_pipe_size(unsigned int size)
+unsigned int round_pipe_size(unsigned long size)
 {
-       unsigned long nr_pages;
-
-       if (size < pipe_min_size)
-               size = pipe_min_size;
-
-       nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
-       if (nr_pages == 0)
+       if (size > (1U << 31))
                return 0;
 
-       return roundup_pow_of_two(nr_pages) << PAGE_SHIFT;
+       /* Minimum pipe size, as required by POSIX */
+       if (size < PAGE_SIZE)
+               return PAGE_SIZE;
+
+       return roundup_pow_of_two(size);
 }
 
 /*
@@ -1046,8 +1049,6 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
        long ret = 0;
 
        size = round_pipe_size(arg);
-       if (size == 0)
-               return -EINVAL;
        nr_pages = size >> PAGE_SHIFT;
 
        if (!nr_pages)
@@ -1069,7 +1070,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg)
        if (nr_pages > pipe->buffers &&
                        (too_many_pipe_buffers_hard(user_bufs) ||
                         too_many_pipe_buffers_soft(user_bufs)) &&
-                       !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
+                       is_unprivileged_user()) {
                ret = -EPERM;
                goto out_revert_acct;
        }
@@ -1124,16 +1125,6 @@ out_revert_acct:
        return ret;
 }
 
-/*
- * This should work even if CONFIG_PROC_FS isn't set, as proc_dopipe_max_size
- * will return an error.
- */
-int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf,
-                size_t *lenp, loff_t *ppos)
-{
-       return proc_dopipe_max_size(table, write, buf, lenp, ppos);
-}
-
 /*
  * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
  * location, so checking ->i_pipe is not enough to verify that this is a