diff options
-rw-r--r-- | fs/pipe.c | 18 | ||||
-rw-r--r-- | include/linux/pipe_fs_i.h | 1 | ||||
-rw-r--r-- | include/linux/sysctl.h | 3 | ||||
-rw-r--r-- | kernel/sysctl.c | 49 |
4 files changed, 56 insertions, 15 deletions
@@ -1020,7 +1020,7 @@ const struct file_operations pipefifo_fops = { | |||
1020 | * Currently we rely on the pipe array holding a power-of-2 number | 1020 | * Currently we rely on the pipe array holding a power-of-2 number |
1021 | * of pages. Returns 0 on error. | 1021 | * of pages. Returns 0 on error. |
1022 | */ | 1022 | */ |
1023 | static inline unsigned int round_pipe_size(unsigned int size) | 1023 | unsigned int round_pipe_size(unsigned int size) |
1024 | { | 1024 | { |
1025 | unsigned long nr_pages; | 1025 | unsigned long nr_pages; |
1026 | 1026 | ||
@@ -1125,25 +1125,13 @@ out_revert_acct: | |||
1125 | } | 1125 | } |
1126 | 1126 | ||
1127 | /* | 1127 | /* |
1128 | * This should work even if CONFIG_PROC_FS isn't set, as proc_dointvec_minmax | 1128 | * This should work even if CONFIG_PROC_FS isn't set, as proc_dopipe_max_size |
1129 | * will return an error. | 1129 | * will return an error. |
1130 | */ | 1130 | */ |
1131 | int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf, | 1131 | int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf, |
1132 | size_t *lenp, loff_t *ppos) | 1132 | size_t *lenp, loff_t *ppos) |
1133 | { | 1133 | { |
1134 | unsigned int rounded_pipe_max_size; | 1134 | return proc_dopipe_max_size(table, write, buf, lenp, ppos); |
1135 | int ret; | ||
1136 | |||
1137 | ret = proc_douintvec_minmax(table, write, buf, lenp, ppos); | ||
1138 | if (ret < 0 || !write) | ||
1139 | return ret; | ||
1140 | |||
1141 | rounded_pipe_max_size = round_pipe_size(pipe_max_size); | ||
1142 | if (rounded_pipe_max_size == 0) | ||
1143 | return -EINVAL; | ||
1144 | |||
1145 | pipe_max_size = rounded_pipe_max_size; | ||
1146 | return ret; | ||
1147 | } | 1135 | } |
1148 | 1136 | ||
1149 | /* | 1137 | /* |
diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 6a80cfc63e0c..2dc5e9870fcd 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h | |||
@@ -191,5 +191,6 @@ long pipe_fcntl(struct file *, unsigned int, unsigned long arg); | |||
191 | struct pipe_inode_info *get_pipe_info(struct file *file); | 191 | struct pipe_inode_info *get_pipe_info(struct file *file); |
192 | 192 | ||
193 | int create_pipe_files(struct file **, int); | 193 | int create_pipe_files(struct file **, int); |
194 | unsigned int round_pipe_size(unsigned int size); | ||
194 | 195 | ||
195 | #endif | 196 | #endif |
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index b769ecfcc3bd..992bc9948232 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h | |||
@@ -51,6 +51,9 @@ extern int proc_dointvec_minmax(struct ctl_table *, int, | |||
51 | extern int proc_douintvec_minmax(struct ctl_table *table, int write, | 51 | extern int proc_douintvec_minmax(struct ctl_table *table, int write, |
52 | void __user *buffer, size_t *lenp, | 52 | void __user *buffer, size_t *lenp, |
53 | loff_t *ppos); | 53 | loff_t *ppos); |
54 | extern int proc_dopipe_max_size(struct ctl_table *table, int write, | ||
55 | void __user *buffer, size_t *lenp, | ||
56 | loff_t *ppos); | ||
54 | extern int proc_dointvec_jiffies(struct ctl_table *, int, | 57 | extern int proc_dointvec_jiffies(struct ctl_table *, int, |
55 | void __user *, size_t *, loff_t *); | 58 | void __user *, size_t *, loff_t *); |
56 | extern int proc_dointvec_userhz_jiffies(struct ctl_table *, int, | 59 | extern int proc_dointvec_userhz_jiffies(struct ctl_table *, int, |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 2d42183b4c98..138b6484f277 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -66,6 +66,7 @@ | |||
66 | #include <linux/kexec.h> | 66 | #include <linux/kexec.h> |
67 | #include <linux/bpf.h> | 67 | #include <linux/bpf.h> |
68 | #include <linux/mount.h> | 68 | #include <linux/mount.h> |
69 | #include <linux/pipe_fs_i.h> | ||
69 | 70 | ||
70 | #include <linux/uaccess.h> | 71 | #include <linux/uaccess.h> |
71 | #include <asm/processor.h> | 72 | #include <asm/processor.h> |
@@ -2620,6 +2621,47 @@ int proc_douintvec_minmax(struct ctl_table *table, int write, | |||
2620 | do_proc_douintvec_minmax_conv, ¶m); | 2621 | do_proc_douintvec_minmax_conv, ¶m); |
2621 | } | 2622 | } |
2622 | 2623 | ||
2624 | struct do_proc_dopipe_max_size_conv_param { | ||
2625 | unsigned int *min; | ||
2626 | }; | ||
2627 | |||
2628 | static int do_proc_dopipe_max_size_conv(unsigned long *lvalp, | ||
2629 | unsigned int *valp, | ||
2630 | int write, void *data) | ||
2631 | { | ||
2632 | struct do_proc_dopipe_max_size_conv_param *param = data; | ||
2633 | |||
2634 | if (write) { | ||
2635 | unsigned int val = round_pipe_size(*lvalp); | ||
2636 | |||
2637 | if (val == 0) | ||
2638 | return -EINVAL; | ||
2639 | |||
2640 | if (param->min && *param->min > val) | ||
2641 | return -ERANGE; | ||
2642 | |||
2643 | if (*lvalp > UINT_MAX) | ||
2644 | return -EINVAL; | ||
2645 | |||
2646 | *valp = val; | ||
2647 | } else { | ||
2648 | unsigned int val = *valp; | ||
2649 | *lvalp = (unsigned long) val; | ||
2650 | } | ||
2651 | |||
2652 | return 0; | ||
2653 | } | ||
2654 | |||
2655 | int proc_dopipe_max_size(struct ctl_table *table, int write, | ||
2656 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2657 | { | ||
2658 | struct do_proc_dopipe_max_size_conv_param param = { | ||
2659 | .min = (unsigned int *) table->extra1, | ||
2660 | }; | ||
2661 | return do_proc_douintvec(table, write, buffer, lenp, ppos, | ||
2662 | do_proc_dopipe_max_size_conv, ¶m); | ||
2663 | } | ||
2664 | |||
2623 | static void validate_coredump_safety(void) | 2665 | static void validate_coredump_safety(void) |
2624 | { | 2666 | { |
2625 | #ifdef CONFIG_COREDUMP | 2667 | #ifdef CONFIG_COREDUMP |
@@ -3125,6 +3167,12 @@ int proc_douintvec_minmax(struct ctl_table *table, int write, | |||
3125 | return -ENOSYS; | 3167 | return -ENOSYS; |
3126 | } | 3168 | } |
3127 | 3169 | ||
3170 | int proc_dopipe_max_size(struct ctl_table *table, int write, | ||
3171 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
3172 | { | ||
3173 | return -ENOSYS; | ||
3174 | } | ||
3175 | |||
3128 | int proc_dointvec_jiffies(struct ctl_table *table, int write, | 3176 | int proc_dointvec_jiffies(struct ctl_table *table, int write, |
3129 | void __user *buffer, size_t *lenp, loff_t *ppos) | 3177 | void __user *buffer, size_t *lenp, loff_t *ppos) |
3130 | { | 3178 | { |
@@ -3168,6 +3216,7 @@ EXPORT_SYMBOL(proc_douintvec); | |||
3168 | EXPORT_SYMBOL(proc_dointvec_jiffies); | 3216 | EXPORT_SYMBOL(proc_dointvec_jiffies); |
3169 | EXPORT_SYMBOL(proc_dointvec_minmax); | 3217 | EXPORT_SYMBOL(proc_dointvec_minmax); |
3170 | EXPORT_SYMBOL_GPL(proc_douintvec_minmax); | 3218 | EXPORT_SYMBOL_GPL(proc_douintvec_minmax); |
3219 | EXPORT_SYMBOL_GPL(proc_dopipe_max_size); | ||
3171 | EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); | 3220 | EXPORT_SYMBOL(proc_dointvec_userhz_jiffies); |
3172 | EXPORT_SYMBOL(proc_dointvec_ms_jiffies); | 3221 | EXPORT_SYMBOL(proc_dointvec_ms_jiffies); |
3173 | EXPORT_SYMBOL(proc_dostring); | 3222 | EXPORT_SYMBOL(proc_dostring); |