* [PATCH v2 3/7] pipe: actually allow root to exceed the pipe buffer limits
[not found] <20180111052902.14409-1-ebiggers3@gmail.com>
@ 2018-01-11 5:28 ` Eric Biggers
2018-01-11 5:28 ` [PATCH v2 4/7] pipe: fix off-by-one error when checking " Eric Biggers
1 sibling, 0 replies; 2+ messages in thread
From: Eric Biggers @ 2018-01-11 5:28 UTC (permalink / raw)
To: linux-fsdevel
Cc: Alexander Viro, Joe Lawrence, Michael Kerrisk, Willy Tarreau,
Mikulas Patocka, Luis R . Rodriguez, Kees Cook, linux-kernel,
Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
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.
Fixes: 759c01142a5d ("pipe: limit the per-user amount of pages allocated in pipes")
Cc: stable@vger.kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/pipe.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/fs/pipe.c b/fs/pipe.c
index d0dec5e7ef33..847ecc388820 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -613,6 +613,11 @@ static bool too_many_pipe_buffers_hard(unsigned long user_bufs)
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;
@@ -629,12 +634,12 @@ struct pipe_inode_info *alloc_pipe_info(void)
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),
@@ -1065,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;
}
--
2.15.1
^ permalink raw reply related [flat|nested] 2+ messages in thread* [PATCH v2 4/7] pipe: fix off-by-one error when checking buffer limits
[not found] <20180111052902.14409-1-ebiggers3@gmail.com>
2018-01-11 5:28 ` [PATCH v2 3/7] pipe: actually allow root to exceed the pipe buffer limits Eric Biggers
@ 2018-01-11 5:28 ` Eric Biggers
1 sibling, 0 replies; 2+ messages in thread
From: Eric Biggers @ 2018-01-11 5:28 UTC (permalink / raw)
To: linux-fsdevel
Cc: Alexander Viro, Joe Lawrence, Michael Kerrisk, Willy Tarreau,
Mikulas Patocka, Luis R . Rodriguez, Kees Cook, linux-kernel,
Eric Biggers, stable
From: Eric Biggers <ebiggers@google.com>
With pipe-user-pages-hard set to 'N', users were actually only allowed
up to 'N - 1' buffers; and likewise for pipe-user-pages-soft.
Fix this to allow up to 'N' buffers, as would be expected.
Fixes: b0b91d18e2e9 ("pipe: fix limit checking in pipe_set_size()")
Cc: stable@vger.kernel.org
Acked-by: Willy Tarreau <w@1wt.eu>
Signed-off-by: Eric Biggers <ebiggers@google.com>
---
fs/pipe.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/pipe.c b/fs/pipe.c
index 847ecc388820..9f20e7128578 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -605,12 +605,12 @@ 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;
+ return pipe_user_pages_soft && user_bufs > pipe_user_pages_soft;
}
static bool too_many_pipe_buffers_hard(unsigned long user_bufs)
{
- return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard;
+ return pipe_user_pages_hard && user_bufs > pipe_user_pages_hard;
}
static bool is_unprivileged_user(void)
--
2.15.1
^ permalink raw reply related [flat|nested] 2+ messages in thread