aboutsummaryrefslogtreecommitdiffstats
path: root/mm/process_vm_access.c
diff options
context:
space:
mode:
authorChristopher Yeoh <cyeoh@au1.ibm.com>2012-02-01 20:04:09 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2012-02-02 15:55:17 -0500
commit8cdb878dcb359fd1137e9abdee9322f5e9bcfdf8 (patch)
tree146afc01f3c1d7cbc944328484d077032bc53bfd /mm/process_vm_access.c
parent24b36da33c64368775f4ef9386d44dce1d2bc8cf (diff)
Fix race in process_vm_rw_core
This fixes the race in process_vm_core found by Oleg (see http://article.gmane.org/gmane.linux.kernel/1235667/ for details). This has been updated since I last sent it as the creation of the new mm_access() function did almost exactly the same thing as parts of the previous version of this patch did. In order to use mm_access() even when /proc isn't enabled, we move it to kernel/fork.c where other related process mm access functions already are. Signed-off-by: Chris Yeoh <yeohc@au1.ibm.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/process_vm_access.c')
-rw-r--r--mm/process_vm_access.c23
1 files changed, 9 insertions, 14 deletions
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
index e920aa3ce10..c20ff48994c 100644
--- a/mm/process_vm_access.c
+++ b/mm/process_vm_access.c
@@ -298,23 +298,18 @@ static ssize_t process_vm_rw_core(pid_t pid, const struct iovec *lvec,
298 goto free_proc_pages; 298 goto free_proc_pages;
299 } 299 }
300 300
301 task_lock(task); 301 mm = mm_access(task, PTRACE_MODE_ATTACH);
302 if (__ptrace_may_access(task, PTRACE_MODE_ATTACH)) { 302 if (!mm || IS_ERR(mm)) {
303 task_unlock(task); 303 rc = IS_ERR(mm) ? PTR_ERR(mm) : -ESRCH;
304 rc = -EPERM; 304 /*
305 goto put_task_struct; 305 * Explicitly map EACCES to EPERM as EPERM is a more a
306 } 306 * appropriate error code for process_vw_readv/writev
307 mm = task->mm; 307 */
308 308 if (rc == -EACCES)
309 if (!mm || (task->flags & PF_KTHREAD)) { 309 rc = -EPERM;
310 task_unlock(task);
311 rc = -EINVAL;
312 goto put_task_struct; 310 goto put_task_struct;
313 } 311 }
314 312
315 atomic_inc(&mm->mm_users);
316 task_unlock(task);
317
318 for (i = 0; i < riovcnt && iov_l_curr_idx < liovcnt; i++) { 313 for (i = 0; i < riovcnt && iov_l_curr_idx < liovcnt; i++) {
319 rc = process_vm_rw_single_vec( 314 rc = process_vm_rw_single_vec(
320 (unsigned long)rvec[i].iov_base, rvec[i].iov_len, 315 (unsigned long)rvec[i].iov_base, rvec[i].iov_len,