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 /mm/util.c | |
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 'mm/util.c')
-rw-r--r-- | mm/util.c | 16 |
1 files changed, 12 insertions, 4 deletions
@@ -476,17 +476,25 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen) | |||
476 | int res = 0; | 476 | int res = 0; |
477 | unsigned int len; | 477 | unsigned int len; |
478 | struct mm_struct *mm = get_task_mm(task); | 478 | struct mm_struct *mm = get_task_mm(task); |
479 | unsigned long arg_start, arg_end, env_start, env_end; | ||
479 | if (!mm) | 480 | if (!mm) |
480 | goto out; | 481 | goto out; |
481 | if (!mm->arg_end) | 482 | if (!mm->arg_end) |
482 | goto out_mm; /* Shh! No looking before we're done */ | 483 | goto out_mm; /* Shh! No looking before we're done */ |
483 | 484 | ||
484 | len = mm->arg_end - mm->arg_start; | 485 | down_read(&mm->mmap_sem); |
486 | arg_start = mm->arg_start; | ||
487 | arg_end = mm->arg_end; | ||
488 | env_start = mm->env_start; | ||
489 | env_end = mm->env_end; | ||
490 | up_read(&mm->mmap_sem); | ||
491 | |||
492 | len = arg_end - arg_start; | ||
485 | 493 | ||
486 | if (len > buflen) | 494 | if (len > buflen) |
487 | len = buflen; | 495 | len = buflen; |
488 | 496 | ||
489 | res = access_process_vm(task, mm->arg_start, buffer, len, 0); | 497 | res = access_process_vm(task, arg_start, buffer, len, 0); |
490 | 498 | ||
491 | /* | 499 | /* |
492 | * If the nul at the end of args has been overwritten, then | 500 | * If the nul at the end of args has been overwritten, then |
@@ -497,10 +505,10 @@ int get_cmdline(struct task_struct *task, char *buffer, int buflen) | |||
497 | if (len < res) { | 505 | if (len < res) { |
498 | res = len; | 506 | res = len; |
499 | } else { | 507 | } else { |
500 | len = mm->env_end - mm->env_start; | 508 | len = env_end - env_start; |
501 | if (len > buflen - res) | 509 | if (len > buflen - res) |
502 | len = buflen - res; | 510 | len = buflen - res; |
503 | res += access_process_vm(task, mm->env_start, | 511 | res += access_process_vm(task, env_start, |
504 | buffer+res, len, 0); | 512 | buffer+res, len, 0); |
505 | res = strnlen(buffer, res); | 513 | res = strnlen(buffer, res); |
506 | } | 514 | } |