4.9-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Biggers <ebigg...@google.com>

commit 85c2dd5473b2718b4b63e74bfeb1ca876868e11f upstream.

pipe-user-pages-hard and pipe-user-pages-soft are only supposed to apply
to unprivileged users, as documented in both Documentation/sysctl/fs.txt
and the pipe(7) man page.

However, the capabilities are actually only checked when increasing a
pipe's size using F_SETPIPE_SZ, not when creating a new pipe.  Therefore,
if pipe-user-pages-hard has been set, the root user can run into it and be
unable to create pipes.  Similarly, if pipe-user-pages-soft has been set,
the root user can run into it and have their pipes limited to 1 page each.

Fix this by allowing the privileged override in both cases.

Link: http://lkml.kernel.org/r/20180111052902.14409-4-ebigge...@gmail.com
Fixes: 759c01142a5d ("pipe: limit the per-user amount of pages allocated in 
pipes")
Signed-off-by: Eric Biggers <ebigg...@google.com>
Acked-by: Kees Cook <keesc...@chromium.org>
Acked-by: Joe Lawrence <joe.lawre...@redhat.com>
Cc: Alexander Viro <v...@zeniv.linux.org.uk>
Cc: "Luis R . Rodriguez" <mcg...@kernel.org>
Cc: Michael Kerrisk <mtk.manpa...@gmail.com>
Cc: Mikulas Patocka <mpato...@redhat.com>
Cc: Willy Tarreau <w...@1wt.eu>
Signed-off-by: Andrew Morton <a...@linux-foundation.org>
Signed-off-by: Linus Torvalds <torva...@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 fs/pipe.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -617,6 +617,11 @@ static bool too_many_pipe_buffers_hard(u
        return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard;
 }
 
+static bool is_unprivileged_user(void)
+{
+       return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
+}
+
 struct pipe_inode_info *alloc_pipe_info(void)
 {
        struct pipe_inode_info *pipe;
@@ -633,12 +638,12 @@ struct pipe_inode_info *alloc_pipe_info(
 
        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),
@@ -1069,7 +1074,7 @@ static long pipe_set_size(struct pipe_in
        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;
        }


Reply via email to