diff options
author | Mateusz Guzik <mguzik@redhat.com> | 2016-01-20 18:01:05 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-20 20:09:18 -0500 |
commit | a3b609ef9f8b1dbfe97034ccad6cd3fe71fbe7ab (patch) | |
tree | 0162563ac7cab6364a3ec6df61b4b96a876943f4 /fs/proc | |
parent | ddf1d398e517e660207e2c807f76a90df543a217 (diff) |
proc read mm's {arg,env}_{start,end} with mmap semaphore taken.
Only functions doing more than one read are modified. Consumeres
happened to deal with possibly changing data, but it does not seem like
a good thing to rely on.
Signed-off-by: Mateusz Guzik <mguzik@redhat.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Cc: Jarod Wilson <jarod@redhat.com>
Cc: Jan Stancek <jstancek@redhat.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Anshuman Khandual <anshuman.linux@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/base.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index e665097c1da5..4f764c2ac1a5 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -953,6 +953,7 @@ static ssize_t environ_read(struct file *file, char __user *buf, | |||
953 | unsigned long src = *ppos; | 953 | unsigned long src = *ppos; |
954 | int ret = 0; | 954 | int ret = 0; |
955 | struct mm_struct *mm = file->private_data; | 955 | struct mm_struct *mm = file->private_data; |
956 | unsigned long env_start, env_end; | ||
956 | 957 | ||
957 | if (!mm) | 958 | if (!mm) |
958 | return 0; | 959 | return 0; |
@@ -964,19 +965,25 @@ static ssize_t environ_read(struct file *file, char __user *buf, | |||
964 | ret = 0; | 965 | ret = 0; |
965 | if (!atomic_inc_not_zero(&mm->mm_users)) | 966 | if (!atomic_inc_not_zero(&mm->mm_users)) |
966 | goto free; | 967 | goto free; |
968 | |||
969 | down_read(&mm->mmap_sem); | ||
970 | env_start = mm->env_start; | ||
971 | env_end = mm->env_end; | ||
972 | up_read(&mm->mmap_sem); | ||
973 | |||
967 | while (count > 0) { | 974 | while (count > 0) { |
968 | size_t this_len, max_len; | 975 | size_t this_len, max_len; |
969 | int retval; | 976 | int retval; |
970 | 977 | ||
971 | if (src >= (mm->env_end - mm->env_start)) | 978 | if (src >= (env_end - env_start)) |
972 | break; | 979 | break; |
973 | 980 | ||
974 | this_len = mm->env_end - (mm->env_start + src); | 981 | this_len = env_end - (env_start + src); |
975 | 982 | ||
976 | max_len = min_t(size_t, PAGE_SIZE, count); | 983 | max_len = min_t(size_t, PAGE_SIZE, count); |
977 | this_len = min(max_len, this_len); | 984 | this_len = min(max_len, this_len); |
978 | 985 | ||
979 | retval = access_remote_vm(mm, (mm->env_start + src), | 986 | retval = access_remote_vm(mm, (env_start + src), |
980 | page, this_len, 0); | 987 | page, this_len, 0); |
981 | 988 | ||
982 | if (retval <= 0) { | 989 | if (retval <= 0) { |