aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/pipe.c15
-rw-r--r--include/linux/pipe_fs_i.h2
-rw-r--r--kernel/sysctl.c9
3 files changed, 26 insertions, 0 deletions
diff --git a/fs/pipe.c b/fs/pipe.c
index 054b8a6a2c7a..d79872eba09a 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -19,11 +19,18 @@
19#include <linux/pagemap.h> 19#include <linux/pagemap.h>
20#include <linux/audit.h> 20#include <linux/audit.h>
21#include <linux/syscalls.h> 21#include <linux/syscalls.h>
22#include <linux/fcntl.h>
22 23
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
24#include <asm/ioctls.h> 25#include <asm/ioctls.h>
25 26
26/* 27/*
28 * The max size that a non-root user is allowed to grow the pipe. Can
29 * be set by root in /proc/sys/fs/pipe-max-pages
30 */
31unsigned int pipe_max_pages = PIPE_DEF_BUFFERS * 16;
32
33/*
27 * We use a start+len construction, which provides full use of the 34 * We use a start+len construction, which provides full use of the
28 * allocated memory. 35 * allocated memory.
29 * -- Florian Coosmann (FGC) 36 * -- Florian Coosmann (FGC)
@@ -1162,6 +1169,14 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg)
1162 1169
1163 switch (cmd) { 1170 switch (cmd) {
1164 case F_SETPIPE_SZ: 1171 case F_SETPIPE_SZ:
1172 if (!capable(CAP_SYS_ADMIN) && arg > pipe_max_pages)
1173 return -EINVAL;
1174 /*
1175 * The pipe needs to be at least 2 pages large to
1176 * guarantee POSIX behaviour.
1177 */
1178 if (arg < 2)
1179 return -EINVAL;
1165 ret = pipe_set_size(pipe, arg); 1180 ret = pipe_set_size(pipe, arg);
1166 break; 1181 break;
1167 case F_GETPIPE_SZ: 1182 case F_GETPIPE_SZ:
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h
index 65f4282fcbaf..16de3933c45e 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -139,6 +139,8 @@ void pipe_lock(struct pipe_inode_info *);
139void pipe_unlock(struct pipe_inode_info *); 139void pipe_unlock(struct pipe_inode_info *);
140void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); 140void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
141 141
142extern unsigned int pipe_max_pages;
143
142/* Drop the inode semaphore and wait for a pipe event, atomically */ 144/* Drop the inode semaphore and wait for a pipe event, atomically */
143void pipe_wait(struct pipe_inode_info *pipe); 145void pipe_wait(struct pipe_inode_info *pipe);
144 146
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 8686b0f5fc12..c649d1c5fe09 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -52,6 +52,7 @@
52#include <linux/slow-work.h> 52#include <linux/slow-work.h>
53#include <linux/perf_event.h> 53#include <linux/perf_event.h>
54#include <linux/kprobes.h> 54#include <linux/kprobes.h>
55#include <linux/pipe_fs_i.h>
55 56
56#include <asm/uaccess.h> 57#include <asm/uaccess.h>
57#include <asm/processor.h> 58#include <asm/processor.h>
@@ -1423,6 +1424,14 @@ static struct ctl_table fs_table[] = {
1423 .child = binfmt_misc_table, 1424 .child = binfmt_misc_table,
1424 }, 1425 },
1425#endif 1426#endif
1427 {
1428 .procname = "pipe-max-pages",
1429 .data = &pipe_max_pages,
1430 .maxlen = sizeof(int),
1431 .mode = 0644,
1432 .proc_handler = &proc_dointvec_minmax,
1433 .extra1 = &two,
1434 },
1426/* 1435/*
1427 * NOTE: do not add new entries to this table unless you have read 1436 * NOTE: do not add new entries to this table unless you have read
1428 * Documentation/sysctl/ctl_unnumbered.txt 1437 * Documentation/sysctl/ctl_unnumbered.txt