提交 8bc9bb27 编写于 作者: M Michal Hocko 提交者: Cheng Jian

mm, mempolicy: fix up gup usage in lookup_node

mainline inclusion
from mainline-v5.8-rc1
commit 2d3a36a4
category: bugfix
bugzilla: 47439
CVE: NA
---------------------------

ba841078 ("mm/mempolicy: Allow lookup_node() to handle fatal signal")
has added a special casing for 0 return value because that was a possible
gup return value when interrupted by fatal signal.  This has been fixed by
ae46d2aa ("mm/gup: Let __get_user_pages_locked() return -EINTR for
fatal signal") in the mean time so ba841078 can be reverted.

This patch however doesn't go all the way to revert it because the check
for 0 is wrong and confusing here.  Firstly it is inherently unsafe to
access the page when get_user_pages_locked returns 0 (aka no page
returned).

Fortunatelly this will not happen because get_user_pages_locked will not
return 0 when nr_pages > 0 unless FOLL_NOWAIT is specified which is not
the case here.  Document this potential error code in gup code while we
are at it.
Signed-off-by: NMichal Hocko <mhocko@suse.com>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Cc: Peter Xu <peterx@redhat.com>
Link: http://lkml.kernel.org/r/20200421071026.18394-1-mhocko@kernel.orgSigned-off-by: NLinus Torvalds <torvalds@linux-foundation.org>

 Conflicts:
	mm/gup.c
[wangxiongfeng: conflicts in comments ]
Signed-off-by: NXiongfeng Wang <wangxiongfeng2@huawei.com>
Reviewed-by: NJing Xiangfeng <jingxiangfeng@huawei.com>
Reviewed-by: NKefeng  Wang <wangkefeng.wang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: NCheng Jian <cj.chengjian@huawei.com>
上级 169cc12f
...@@ -632,6 +632,7 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags) ...@@ -632,6 +632,7 @@ static int check_vma_flags(struct vm_area_struct *vma, unsigned long gup_flags)
* were pinned, returns -errno. Each page returned must be released * were pinned, returns -errno. Each page returned must be released
* with a put_page() call when it is finished with. vmas will only * with a put_page() call when it is finished with. vmas will only
* remain valid while mmap_sem is held. * remain valid while mmap_sem is held.
* -- 0 return value is possible when the fault would need to be retried.
* *
* Must be called with mmap_sem held. It may be released. See below. * Must be called with mmap_sem held. It may be released. See below.
* *
...@@ -877,6 +878,10 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm, ...@@ -877,6 +878,10 @@ int fixup_user_fault(struct task_struct *tsk, struct mm_struct *mm,
} }
EXPORT_SYMBOL_GPL(fixup_user_fault); EXPORT_SYMBOL_GPL(fixup_user_fault);
/*
* Please note that this function, unlike __get_user_pages will not
* return 0 for nr_pages > 0 without FOLL_NOWAIT
*/
static __always_inline long __get_user_pages_locked(struct task_struct *tsk, static __always_inline long __get_user_pages_locked(struct task_struct *tsk,
struct mm_struct *mm, struct mm_struct *mm,
unsigned long start, unsigned long start,
......
...@@ -901,10 +901,7 @@ static int lookup_node(unsigned long addr) ...@@ -901,10 +901,7 @@ static int lookup_node(unsigned long addr)
int err; int err;
err = get_user_pages(addr & PAGE_MASK, 1, 0, &p, NULL); err = get_user_pages(addr & PAGE_MASK, 1, 0, &p, NULL);
if (err == 0) { if (err > 0) {
/* E.g. GUP interrupted by fatal signal */
err = -EFAULT;
} else if (err > 0) {
err = page_to_nid(p); err = page_to_nid(p);
put_page(p); put_page(p);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册