diff options
| author | Jens Axboe <jens.axboe@oracle.com> | 2010-05-19 15:03:16 -0400 |
|---|---|---|
| committer | Jens Axboe <jens.axboe@oracle.com> | 2010-05-21 15:12:52 -0400 |
| commit | b492e95be0ae672922f4734acf3f5d35c30be948 (patch) | |
| tree | a8a1e7f035903796e6b8f626add8d269bf989a35 | |
| parent | 35f3d14dbbc58447c61e38a162ea10add6b31dc7 (diff) | |
pipe: set lower and upper limit on max pages in the pipe page array
We need at least two to guarantee proper POSIX behaviour, so
never allow a smaller limit than that.
Also expose a /proc/sys/fs/pipe-max-pages sysctl file that allows
root to define a sane upper limit. Make it default to 16 times the
default size, which is 16 pages.
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
| -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 |
