Pull more vfs updates from Al Viro: "Embarrassing braino fix + pipe page accounting + fixing an eyesore in find_filesystem() (checking that s1 is equal to prefix of s2 of given length can be done in many ways, but "compare strlen(s1) with length and then do strncmp()" is not a good one...)" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: [regression] fix braino in fs/dlm/user.c pipe: limit the per-user amount of pages allocated in pipes find_filesystem(): simplify comparison
Unified · Split
| @@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs: · 31 unmodified lines | ||
| 32 | 32 | - nr_open |
| 33 | 33 | - overflowuid |
| 34 | 34 | - overflowgid |
| 35 | +- pipe-user-pages-hard | |
| 36 | +- pipe-user-pages-soft | |
| 35 | 37 | - protected_hardlinks |
| 36 | 38 | - protected_symlinks |
| 37 | 39 | - suid_dumpable |
| @@ -159,6 +161,27 @@ The default is 65534. · 121 unmodified lines | ||
| 159 | 161 | |
| 160 | 162 | ============================================================== |
| 161 | 163 | |
| 164 | +pipe-user-pages-hard: | |
| 165 | + | |
| 166 | +Maximum total number of pages a non-privileged user may allocate for pipes. | |
| 167 | +Once this limit is reached, no new pipes may be allocated until usage goes | |
| 168 | +below the limit again. When set to 0, no limit is applied, which is the default | |
| 169 | +setting. | |
| 170 | + | |
| 171 | +============================================================== | |
| 172 | + | |
| 173 | +pipe-user-pages-soft: | |
| 174 | + | |
| 175 | +Maximum total number of pages a non-privileged user may allocate for pipes | |
| 176 | +before the pipe size gets limited to a single page. Once this limit is reached, | |
| 177 | +new pipes will be limited to a single page in size for this user in order to | |
| 178 | +limit total memory usage, and trying to increase them using fcntl() will be | |
| 179 | +denied until usage goes below the limit again. The default value allows to | |
| 180 | +allocate up to 1024 pipes at their default size. When set to 0, no limit is | |
| 181 | +applied. | |
| 182 | + | |
| 183 | +============================================================== | |
| 184 | + | |
| 162 | 185 | protected_hardlinks: |
| 163 | 186 | |
| 164 | 187 | A long-standing class of security issues is the hardlink-based |
| @@ -516,7 +516,7 @@ static ssize_t device_write(struct file *file, const char __user *buf, · 515 unmodified lines | ||
| 516 | 516 | return -EINVAL; |
| 517 | 517 | |
| 518 | 518 | kbuf = memdup_user_nul(buf, count); |
| 519 | − if (!IS_ERR(kbuf)) | |
| 519 | + if (IS_ERR(kbuf)) | |
| 520 | 520 | return PTR_ERR(kbuf); |
| 521 | 521 | |
| 522 | 522 | if (check_version(kbuf)) { |
| @@ -46,9 +46,9 @@ void put_filesystem(struct file_system_type *fs) · 45 unmodified lines | ||
| 46 | 46 | static struct file_system_type **find_filesystem(const char *name, unsigned len) |
| 47 | 47 | { |
| 48 | 48 | struct file_system_type **p; |
| 49 | − for (p=&file_systems; *p; p=&(*p)->next) | |
| 50 | − if (strlen((*p)->name) == len && | |
| 51 | − strncmp((*p)->name, name, len) == 0) | |
| 49 | + for (p = &file_systems; *p; p = &(*p)->next) | |
| 50 | + if (strncmp((*p)->name, name, len) == 0 && | |
| 51 | + !(*p)->name[len]) | |
| 52 | 52 | break; |
| 53 | 53 | return p; |
| 54 | 54 | } |
| @@ -38,6 +38,12 @@ unsigned int pipe_max_size = 1048576; · 37 unmodified lines | ||
| 38 | 38 | */ |
| 39 | 39 | unsigned int pipe_min_size = PAGE_SIZE; |
| 40 | 40 | |
| 41 | +/* Maximum allocatable pages per user. Hard limit is unset by default, soft | |
| 42 | + * matches default values. | |
| 43 | + */ | |
| 44 | +unsigned long pipe_user_pages_hard; | |
| 45 | +unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR; | |
| 46 | + | |
| 41 | 47 | /* |
| 42 | 48 | * We use a start+len construction, which provides full use of the |
| 43 | 49 | * allocated memory. |
| @@ -583,20 +589,49 @@ pipe_fasync(int fd, struct file *filp, int on) · 539 unmodified lines | ||
| 583 | 589 | return retval; |
| 584 | 590 | } |
| 585 | 591 | |
| 592 | +static void account_pipe_buffers(struct pipe_inode_info *pipe, | |
| 593 | + unsigned long old, unsigned long new) | |
| 594 | +{ | |
| 595 | + atomic_long_add(new - old, &pipe->user->pipe_bufs); | |
| 596 | +} | |
| 597 | + | |
| 598 | +static bool too_many_pipe_buffers_soft(struct user_struct *user) | |
| 599 | +{ | |
| 600 | + return pipe_user_pages_soft && | |
| 601 | + atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft; | |
| 602 | +} | |
| 603 | + | |
| 604 | +static bool too_many_pipe_buffers_hard(struct user_struct *user) | |
| 605 | +{ | |
| 606 | + return pipe_user_pages_hard && | |
| 607 | + atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard; | |
| 608 | +} | |
| 609 | + | |
| 586 | 610 | struct pipe_inode_info *alloc_pipe_info(void) |
| 587 | 611 | { |
| 588 | 612 | struct pipe_inode_info *pipe; |
| 589 | 613 | |
| 590 | 614 | pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL); |
| 591 | 615 | if (pipe) { |
| 592 | − pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL); | |
| 616 | + unsigned long pipe_bufs = PIPE_DEF_BUFFERS; | |
| 617 | + struct user_struct *user = get_current_user(); | |
| 618 | + | |
| 619 | + if (!too_many_pipe_buffers_hard(user)) { | |
| 620 | + if (too_many_pipe_buffers_soft(user)) | |
| 621 | + pipe_bufs = 1; | |
| 622 | + pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL); | |
| 623 | + } | |
| 624 | + | |
| 593 | 625 | if (pipe->bufs) { |
| 594 | 626 | init_waitqueue_head(&pipe->wait); |
| 595 | 627 | pipe->r_counter = pipe->w_counter = 1; |
| 596 | − pipe->buffers = PIPE_DEF_BUFFERS; | |
| 628 | + pipe->buffers = pipe_bufs; | |
| 629 | + pipe->user = user; | |
| 630 | + account_pipe_buffers(pipe, 0, pipe_bufs); | |
| 597 | 631 | mutex_init(&pipe->mutex); |
| 598 | 632 | return pipe; |
| 599 | 633 | } |
| 634 | + free_uid(user); | |
| 600 | 635 | kfree(pipe); |
| 601 | 636 | } |
| 602 | 637 | |
| @@ -607,6 +642,8 @@ void free_pipe_info(struct pipe_inode_info *pipe) · 4 unmodified lines | ||
| 607 | 642 | { |
| 608 | 643 | int i; |
| 609 | 644 | |
| 645 | + account_pipe_buffers(pipe, pipe->buffers, 0); | |
| 646 | + free_uid(pipe->user); | |
| 610 | 647 | for (i = 0; i < pipe->buffers; i++) { |
| 611 | 648 | struct pipe_buffer *buf = pipe->bufs + i; |
| 612 | 649 | if (buf->ops) |
| @@ -998,6 +1035,7 @@ static long pipe_set_size(struct pipe_inode_info *pipe, unsigned long nr_pages) · 385 unmodified lines | ||
| 998 | 1035 | memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer)); |
| 999 | 1036 | } |
| 1000 | 1037 | |
| 1038 | + account_pipe_buffers(pipe, pipe->buffers, nr_pages); | |
| 1001 | 1039 | pipe->curbuf = 0; |
| 1002 | 1040 | kfree(pipe->bufs); |
| 1003 | 1041 | pipe->bufs = bufs; |
| @@ -1069,6 +1107,11 @@ long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) · 65 unmodified lines | ||
| 1069 | 1107 | if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) { |
| 1070 | 1108 | ret = -EPERM; |
| 1071 | 1109 | goto out; |
| 1110 | + } else if ((too_many_pipe_buffers_hard(pipe->user) || | |
| 1111 | + too_many_pipe_buffers_soft(pipe->user)) && | |
| 1112 | + !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) { | |
| 1113 | + ret = -EPERM; | |
| 1114 | + goto out; | |
| 1072 | 1115 | } |
| 1073 | 1116 | ret = pipe_set_size(pipe, nr_pages); |
| 1074 | 1117 | break; |
| @@ -42,6 +42,7 @@ struct pipe_buffer { · 41 unmodified lines | ||
| 42 | 42 | * @fasync_readers: reader side fasync |
| 43 | 43 | * @fasync_writers: writer side fasync |
| 44 | 44 | * @bufs: the circular array of pipe buffers |
| 45 | + * @user: the user who created this pipe | |
| 45 | 46 | **/ |
| 46 | 47 | struct pipe_inode_info { |
| 47 | 48 | struct mutex mutex; |
| @@ -57,6 +58,7 @@ struct pipe_inode_info { · 9 unmodified lines | ||
| 57 | 58 | struct fasync_struct *fasync_readers; |
| 58 | 59 | struct fasync_struct *fasync_writers; |
| 59 | 60 | struct pipe_buffer *bufs; |
| 61 | + struct user_struct *user; | |
| 60 | 62 | }; |
| 61 | 63 | |
| 62 | 64 | /* |
| @@ -123,6 +125,8 @@ void pipe_unlock(struct pipe_inode_info *); · 60 unmodified lines | ||
| 123 | 125 | void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *); |
| 124 | 126 | |
| 125 | 127 | extern unsigned int pipe_max_size, pipe_min_size; |
| 128 | +extern unsigned long pipe_user_pages_hard; | |
| 129 | +extern unsigned long pipe_user_pages_soft; | |
| 126 | 130 | int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *); |
| 127 | 131 | |
| 128 | 132 | |
| @@ -835,6 +835,7 @@ struct user_struct { · 834 unmodified lines | ||
| 835 | 835 | #endif |
| 836 | 836 | unsigned long locked_shm; /* How many pages of mlocked shm ? */ |
| 837 | 837 | unsigned long unix_inflight; /* How many files in flight in unix sockets */ |
| 838 | + atomic_long_t pipe_bufs; /* how many pages are allocated in pipe buffers */ | |
| 838 | 839 | |
| 839 | 840 | #ifdef CONFIG_KEYS |
| 840 | 841 | struct key *uid_keyring; /* UID specific keyring */ |
| @@ -1757,6 +1757,20 @@ static struct ctl_table fs_table[] = { · 1756 unmodified lines | ||
| 1757 | 1757 | .proc_handler = &pipe_proc_fn, |
| 1758 | 1758 | .extra1 = &pipe_min_size, |
| 1759 | 1759 | }, |
| 1760 | + { | |
| 1761 | + .procname = "pipe-user-pages-hard", | |
| 1762 | + .data = &pipe_user_pages_hard, | |
| 1763 | + .maxlen = sizeof(pipe_user_pages_hard), | |
| 1764 | + .mode = 0644, | |
| 1765 | + .proc_handler = proc_doulongvec_minmax, | |
| 1766 | + }, | |
| 1767 | + { | |
| 1768 | + .procname = "pipe-user-pages-soft", | |
| 1769 | + .data = &pipe_user_pages_soft, | |
| 1770 | + .maxlen = sizeof(pipe_user_pages_soft), | |
| 1771 | + .mode = 0644, | |
| 1772 | + .proc_handler = proc_doulongvec_minmax, | |
| 1773 | + }, | |
| 1760 | 1774 | { } |
| 1761 | 1775 | }; |
| 1762 | 1776 | |