diff mbox series

[V2] mm: fix potential pte_unmap_unlock pte error

Message ID 20201017021151.28104-1-luoshijie1@huawei.com (mailing list archive)
State New, archived
Headers show
Series [V2] mm: fix potential pte_unmap_unlock pte error | expand

Commit Message

Shijie Luo Oct. 17, 2020, 2:11 a.m. UTC
When flags don't have MPOL_MF_MOVE or MPOL_MF_MOVE_ALL bits, code breaks
 and passing origin pte - 1 to pte_unmap_unlock seems like not a good idea.

Signed-off-by: Shijie Luo <luoshijie1@huawei.com>
Signed-off-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>
---
 mm/mempolicy.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

Comments

Michal Hocko Oct. 19, 2020, 6:59 a.m. UTC | #1
On Fri 16-10-20 22:11:51, Shijie Luo wrote:
> When flags don't have MPOL_MF_MOVE or MPOL_MF_MOVE_ALL bits, code breaks
>  and passing origin pte - 1 to pte_unmap_unlock seems like not a good idea.

This would really benefit from some improvements. It is preferable to
provide a user visibile effect of the patch. I would propose this, feel
free to reuse parts as you find fit.
"
queue_pages_pte_range can run in MPOL_MF_MOVE_ALL mode which doesn't
migrate misplaced pages but returns with EIO when encountering such a
page. Since a7f40cfe3b7a ("mm: mempolicy: make mbind() return -EIO when
MPOL_MF_STRICT is specified") and early break on the first pte in the
range results in pte_unmap_unlock on an underflow pte. This can lead to
lockups later on when somebody tries to lock the pte resp.
page_table_lock again..

Fixes: a7f40cfe3b7a ("mm: mempolicy: make mbind() return -EIO when
MPOL_MF_STRICT is specified")
"

> Signed-off-by: Shijie Luo <luoshijie1@huawei.com>
> Signed-off-by: Michal Hocko <mhocko@suse.com>
> Signed-off-by: Miaohe Lin <linmiaohe@huawei.com>

No need to add my s-o-b.

> ---
>  mm/mempolicy.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> index 3fde772ef5ef..3ca4898f3f24 100644
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -525,7 +525,7 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
>  	unsigned long flags = qp->flags;
>  	int ret;
>  	bool has_unmovable = false;
> -	pte_t *pte;
> +	pte_t *pte, *mapped_pte;
>  	spinlock_t *ptl;
>  
>  	ptl = pmd_trans_huge_lock(pmd, vma);
> @@ -539,7 +539,7 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
>  	if (pmd_trans_unstable(pmd))
>  		return 0;
>  
> -	pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
> +	mapped_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
>  	for (; addr != end; pte++, addr += PAGE_SIZE) {
>  		if (!pte_present(*pte))
>  			continue;
> @@ -571,7 +571,7 @@ static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
>  		} else
>  			break;
>  	}
> -	pte_unmap_unlock(pte - 1, ptl);
> +	pte_unmap_unlock(mapped_pte, ptl);
>  	cond_resched();
>  
>  	if (has_unmovable)
> -- 
> 2.19.1
>
Shijie Luo Oct. 19, 2020, 7:25 a.m. UTC | #2
On 2020/10/19 14:59, Michal Hocko wrote:
> On Fri 16-10-20 22:11:51, Shijie Luo wrote:
>> When flags don't have MPOL_MF_MOVE or MPOL_MF_MOVE_ALL bits, code breaks
>>   and passing origin pte - 1 to pte_unmap_unlock seems like not a good idea.
> This would really benefit from some improvements. It is preferable to
> provide a user visibile effect of the patch. I would propose this, feel
> free to reuse parts as you find fit.
> "
> queue_pages_pte_range can run in MPOL_MF_MOVE_ALL mode which doesn't
> migrate misplaced pages but returns with EIO when encountering such a
> page. Since a7f40cfe3b7a ("mm: mempolicy: make mbind() return -EIO when
> MPOL_MF_STRICT is specified") and early break on the first pte in the
> range results in pte_unmap_unlock on an underflow pte. This can lead to
> lockups later on when somebody tries to lock the pte resp.
> page_table_lock again..
>
> Fixes: a7f40cfe3b7a ("mm: mempolicy: make mbind() return -EIO when
> MPOL_MF_STRICT is specified")
> "
I will take these in my patch description and send version 3, Thanks.
diff mbox series

Patch

diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 3fde772ef5ef..3ca4898f3f24 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -525,7 +525,7 @@  static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
 	unsigned long flags = qp->flags;
 	int ret;
 	bool has_unmovable = false;
-	pte_t *pte;
+	pte_t *pte, *mapped_pte;
 	spinlock_t *ptl;
 
 	ptl = pmd_trans_huge_lock(pmd, vma);
@@ -539,7 +539,7 @@  static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
 	if (pmd_trans_unstable(pmd))
 		return 0;
 
-	pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
+	mapped_pte = pte = pte_offset_map_lock(walk->mm, pmd, addr, &ptl);
 	for (; addr != end; pte++, addr += PAGE_SIZE) {
 		if (!pte_present(*pte))
 			continue;
@@ -571,7 +571,7 @@  static int queue_pages_pte_range(pmd_t *pmd, unsigned long addr,
 		} else
 			break;
 	}
-	pte_unmap_unlock(pte - 1, ptl);
+	pte_unmap_unlock(mapped_pte, ptl);
 	cond_resched();
 
 	if (has_unmovable)