proc: put check_mem_permission after __get_free_page in mem_write
It whould be better if put check_mem_permission after __get_free_page in mem_write, to be same as function mem_read. Hugh Dickins explained the reason. check_mem_permission gets a reference to the mm. If we __get_free_page after check_mem_permission, imagine what happens if the system is out of memory, and the mm we're looking at is selected for killing by the OOM killer: while we wait in __get_free_page for more memory, no memory is freed from the selected mm because it cannot reach exit_mmap while we hold that reference. Reported-by: Jovi Zhang <bookjovi@gmail.com> Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Acked-by: Hugh Dickins <hughd@google.com> Reviewed-by: Stephen Wilson <wilsons@start.ca> Cc: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
a4dbf0ec2a
commit
30cd890391
1 changed files with 12 additions and 10 deletions
|
@ -894,18 +894,18 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
|
||||||
if (!task)
|
if (!task)
|
||||||
goto out_no_task;
|
goto out_no_task;
|
||||||
|
|
||||||
mm = check_mem_permission(task);
|
|
||||||
copied = PTR_ERR(mm);
|
|
||||||
if (IS_ERR(mm))
|
|
||||||
goto out_task;
|
|
||||||
|
|
||||||
copied = -EIO;
|
|
||||||
if (file->private_data != (void *)((long)current->self_exec_id))
|
|
||||||
goto out_mm;
|
|
||||||
|
|
||||||
copied = -ENOMEM;
|
copied = -ENOMEM;
|
||||||
page = (char *)__get_free_page(GFP_TEMPORARY);
|
page = (char *)__get_free_page(GFP_TEMPORARY);
|
||||||
if (!page)
|
if (!page)
|
||||||
|
goto out_task;
|
||||||
|
|
||||||
|
mm = check_mem_permission(task);
|
||||||
|
copied = PTR_ERR(mm);
|
||||||
|
if (IS_ERR(mm))
|
||||||
|
goto out_free;
|
||||||
|
|
||||||
|
copied = -EIO;
|
||||||
|
if (file->private_data != (void *)((long)current->self_exec_id))
|
||||||
goto out_mm;
|
goto out_mm;
|
||||||
|
|
||||||
copied = 0;
|
copied = 0;
|
||||||
|
@ -929,9 +929,11 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
|
||||||
count -= retval;
|
count -= retval;
|
||||||
}
|
}
|
||||||
*ppos = dst;
|
*ppos = dst;
|
||||||
free_page((unsigned long) page);
|
|
||||||
out_mm:
|
out_mm:
|
||||||
mmput(mm);
|
mmput(mm);
|
||||||
|
out_free:
|
||||||
|
free_page((unsigned long) page);
|
||||||
out_task:
|
out_task:
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
out_no_task:
|
out_no_task:
|
||||||
|
|
Loading…
Reference in a new issue