diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-07 01:15:42 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-07 01:15:42 -0500 |
commit | a2e5790d841658485d642196dbb0927303d6c22f (patch) | |
tree | b3d28c9bcb7da6880806146fd22a88a7ee7f733e /fs/pipe.c | |
parent | ab2d92ad881da11331280aedf612d82e61cb6d41 (diff) | |
parent | 60c3e026d73ccabb075fb70ba02f8512ab40cf2c (diff) |
Merge branch 'akpm' (patches from Andrew)
Merge misc updates from Andrew Morton:
- kasan updates
- procfs
- lib/bitmap updates
- other lib/ updates
- checkpatch tweaks
- rapidio
- ubsan
- pipe fixes and cleanups
- lots of other misc bits
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (114 commits)
Documentation/sysctl/user.txt: fix typo
MAINTAINERS: update ARM/QUALCOMM SUPPORT patterns
MAINTAINERS: update various PALM patterns
MAINTAINERS: update "ARM/OXNAS platform support" patterns
MAINTAINERS: update Cortina/Gemini patterns
MAINTAINERS: remove ARM/CLKDEV SUPPORT file pattern
MAINTAINERS: remove ANDROID ION pattern
mm: docs: add blank lines to silence sphinx "Unexpected indentation" errors
mm: docs: fix parameter names mismatch
mm: docs: fixup punctuation
pipe: read buffer limits atomically
pipe: simplify round_pipe_size()
pipe: reject F_SETPIPE_SZ with size over UINT_MAX
pipe: fix off-by-one error when checking buffer limits
pipe: actually allow root to exceed the pipe buffer limits
pipe, sysctl: remove pipe_proc_fn()
pipe, sysctl: drop 'min' parameter from pipe-max-size converter
kasan: rework Kconfig settings
crash_dump: is_kdump_kernel can be boolean
kernel/mutex: mutex_is_locked can be boolean
...
Diffstat (limited to 'fs/pipe.c')
-rw-r--r-- | fs/pipe.c | 57 |
1 files changed, 24 insertions, 33 deletions
@@ -35,11 +35,6 @@ | |||
35 | */ | 35 | */ |
36 | unsigned int pipe_max_size = 1048576; | 36 | unsigned int pipe_max_size = 1048576; |
37 | 37 | ||
38 | /* | ||
39 | * Minimum pipe size, as required by POSIX | ||
40 | */ | ||
41 | unsigned int pipe_min_size = PAGE_SIZE; | ||
42 | |||
43 | /* Maximum allocatable pages per user. Hard limit is unset by default, soft | 38 | /* Maximum allocatable pages per user. Hard limit is unset by default, soft |
44 | * matches default values. | 39 | * matches default values. |
45 | */ | 40 | */ |
@@ -610,12 +605,21 @@ static unsigned long account_pipe_buffers(struct user_struct *user, | |||
610 | 605 | ||
611 | static bool too_many_pipe_buffers_soft(unsigned long user_bufs) | 606 | static bool too_many_pipe_buffers_soft(unsigned long user_bufs) |
612 | { | 607 | { |
613 | return pipe_user_pages_soft && user_bufs >= pipe_user_pages_soft; | 608 | unsigned long soft_limit = READ_ONCE(pipe_user_pages_soft); |
609 | |||
610 | return soft_limit && user_bufs > soft_limit; | ||
614 | } | 611 | } |
615 | 612 | ||
616 | static bool too_many_pipe_buffers_hard(unsigned long user_bufs) | 613 | static bool too_many_pipe_buffers_hard(unsigned long user_bufs) |
617 | { | 614 | { |
618 | return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard; | 615 | unsigned long hard_limit = READ_ONCE(pipe_user_pages_hard); |
616 | |||
617 | return hard_limit && user_bufs > hard_limit; | ||
618 | } | ||
619 | |||
620 | static bool is_unprivileged_user(void) | ||
621 | { | ||
622 | return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); | ||
619 | } | 623 | } |
620 | 624 | ||
621 | struct pipe_inode_info *alloc_pipe_info(void) | 625 | struct pipe_inode_info *alloc_pipe_info(void) |
@@ -624,22 +628,23 @@ struct pipe_inode_info *alloc_pipe_info(void) | |||
624 | unsigned long pipe_bufs = PIPE_DEF_BUFFERS; | 628 | unsigned long pipe_bufs = PIPE_DEF_BUFFERS; |
625 | struct user_struct *user = get_current_user(); | 629 | struct user_struct *user = get_current_user(); |
626 | unsigned long user_bufs; | 630 | unsigned long user_bufs; |
631 | unsigned int max_size = READ_ONCE(pipe_max_size); | ||
627 | 632 | ||
628 | pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT); | 633 | pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL_ACCOUNT); |
629 | if (pipe == NULL) | 634 | if (pipe == NULL) |
630 | goto out_free_uid; | 635 | goto out_free_uid; |
631 | 636 | ||
632 | if (pipe_bufs * PAGE_SIZE > pipe_max_size && !capable(CAP_SYS_RESOURCE)) | 637 | if (pipe_bufs * PAGE_SIZE > max_size && !capable(CAP_SYS_RESOURCE)) |
633 | pipe_bufs = pipe_max_size >> PAGE_SHIFT; | 638 | pipe_bufs = max_size >> PAGE_SHIFT; |
634 | 639 | ||
635 | user_bufs = account_pipe_buffers(user, 0, pipe_bufs); | 640 | user_bufs = account_pipe_buffers(user, 0, pipe_bufs); |
636 | 641 | ||
637 | if (too_many_pipe_buffers_soft(user_bufs)) { | 642 | if (too_many_pipe_buffers_soft(user_bufs) && is_unprivileged_user()) { |
638 | user_bufs = account_pipe_buffers(user, pipe_bufs, 1); | 643 | user_bufs = account_pipe_buffers(user, pipe_bufs, 1); |
639 | pipe_bufs = 1; | 644 | pipe_bufs = 1; |
640 | } | 645 | } |
641 | 646 | ||
642 | if (too_many_pipe_buffers_hard(user_bufs)) | 647 | if (too_many_pipe_buffers_hard(user_bufs) && is_unprivileged_user()) |
643 | goto out_revert_acct; | 648 | goto out_revert_acct; |
644 | 649 | ||
645 | pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer), | 650 | pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer), |
@@ -1020,18 +1025,16 @@ const struct file_operations pipefifo_fops = { | |||
1020 | * Currently we rely on the pipe array holding a power-of-2 number | 1025 | * Currently we rely on the pipe array holding a power-of-2 number |
1021 | * of pages. Returns 0 on error. | 1026 | * of pages. Returns 0 on error. |
1022 | */ | 1027 | */ |
1023 | unsigned int round_pipe_size(unsigned int size) | 1028 | unsigned int round_pipe_size(unsigned long size) |
1024 | { | 1029 | { |
1025 | unsigned long nr_pages; | 1030 | if (size > (1U << 31)) |
1026 | |||
1027 | if (size < pipe_min_size) | ||
1028 | size = pipe_min_size; | ||
1029 | |||
1030 | nr_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
1031 | if (nr_pages == 0) | ||
1032 | return 0; | 1031 | return 0; |
1033 | 1032 | ||
1034 | return roundup_pow_of_two(nr_pages) << PAGE_SHIFT; | 1033 | /* Minimum pipe size, as required by POSIX */ |
1034 | if (size < PAGE_SIZE) | ||
1035 | return PAGE_SIZE; | ||
1036 | |||
1037 | return roundup_pow_of_two(size); | ||
1035 | } | 1038 | } |
1036 | 1039 | ||
1037 | /* | 1040 | /* |
@@ -1046,8 +1049,6 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg) | |||
1046 | long ret = 0; | 1049 | long ret = 0; |
1047 | 1050 | ||
1048 | size = round_pipe_size(arg); | 1051 | size = round_pipe_size(arg); |
1049 | if (size == 0) | ||
1050 | return -EINVAL; | ||
1051 | nr_pages = size >> PAGE_SHIFT; | 1052 | nr_pages = size >> PAGE_SHIFT; |
1052 | 1053 | ||
1053 | if (!nr_pages) | 1054 | if (!nr_pages) |
@@ -1069,7 +1070,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long arg) | |||
1069 | if (nr_pages > pipe->buffers && | 1070 | if (nr_pages > pipe->buffers && |
1070 | (too_many_pipe_buffers_hard(user_bufs) || | 1071 | (too_many_pipe_buffers_hard(user_bufs) || |
1071 | too_many_pipe_buffers_soft(user_bufs)) && | 1072 | too_many_pipe_buffers_soft(user_bufs)) && |
1072 | !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) { | 1073 | is_unprivileged_user()) { |
1073 | ret = -EPERM; | 1074 | ret = -EPERM; |
1074 | goto out_revert_acct; | 1075 | goto out_revert_acct; |
1075 | } | 1076 | } |
@@ -1125,16 +1126,6 @@ out_revert_acct: | |||
1125 | } | 1126 | } |
1126 | 1127 | ||
1127 | /* | 1128 | /* |
1128 | * This should work even if CONFIG_PROC_FS isn't set, as proc_dopipe_max_size | ||
1129 | * will return an error. | ||
1130 | */ | ||
1131 | int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf, | ||
1132 | size_t *lenp, loff_t *ppos) | ||
1133 | { | ||
1134 | return proc_dopipe_max_size(table, write, buf, lenp, ppos); | ||
1135 | } | ||
1136 | |||
1137 | /* | ||
1138 | * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same | 1129 | * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same |
1139 | * location, so checking ->i_pipe is not enough to verify that this is a | 1130 | * location, so checking ->i_pipe is not enough to verify that this is a |
1140 | * pipe. | 1131 | * pipe. |