diff options
-rw-r--r-- | fs/pipe.c | 15 | ||||
-rw-r--r-- | include/linux/pipe_fs_i.h | 2 | ||||
-rw-r--r-- | kernel/sysctl.c | 9 |
3 files changed, 26 insertions, 0 deletions
@@ -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 | */ | ||
31 | unsigned 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 *); | |||
139 | void pipe_unlock(struct pipe_inode_info *); | 139 | void pipe_unlock(struct pipe_inode_info *); |
140 | void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); | 140 | void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); |
141 | 141 | ||
142 | extern 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 */ |
143 | void pipe_wait(struct pipe_inode_info *pipe); | 145 | void 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 |