| From: Hugh Dickins <hughd@google.com> |
| Subject: mempolicy: migration attempt to match interleave nodes: fix |
| Date: Mon, 23 Oct 2023 23:50:42 -0700 (PDT) |
| |
| mm-unstable commit edd33b8807a1 ("mempolicy: migration attempt to match |
| interleave nodes") added a second vma_iter search to do_mbind(), to |
| determine the interleave index to be used in the MPOL_INTERLEAVE case. |
| |
| But sadly it added it just after the mmap_write_unlock(), leaving this new |
| VMA search unprotected: and so syzbot reports suspicious RCU usage from |
| lib/maple_tree.c:856. |
| |
| This could be fixed with an rcu_read_lock/unlock() pair (per Liam); but |
| since we have been relying on the mmap_lock up to this point, it's |
| slightly better to extend it over the new search too, for a well-defined |
| result consistent with the policy this mbind() is establishing (rather |
| than whatever might follow once the mmap_lock is dropped). |
| |
| Link: https://lkml.kernel.org/r/3311d544-fb05-a7f1-1b74-16aa0f6cd4fe@google.com |
| Fixes: edd33b8807a1 ("mempolicy: migration attempt to match interleave nodes") |
| Signed-off-by: Hugh Dickins <hughd@google.com> |
| Reported-by: syzbot+79fcba037b6df73756d3@syzkaller.appspotmail.com |
| Closes: https://lore.kernel.org/linux-mm/000000000000c05f1b0608657fde@google.com/ |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| mm/mempolicy.c | 6 ++++-- |
| 1 file changed, 4 insertions(+), 2 deletions(-) |
| |
| --- a/mm/mempolicy.c~mempolicy-migration-attempt-to-match-interleave-nodes-fix |
| +++ a/mm/mempolicy.c |
| @@ -1291,8 +1291,6 @@ static long do_mbind(unsigned long start |
| } |
| } |
| |
| - mmap_write_unlock(mm); |
| - |
| if (!err && !list_empty(&pagelist)) { |
| /* Convert MPOL_DEFAULT's NULL to task or default policy */ |
| if (!new) { |
| @@ -1334,7 +1332,11 @@ static long do_mbind(unsigned long start |
| mmpol.ilx -= page->index >> order; |
| } |
| } |
| + } |
| |
| + mmap_write_unlock(mm); |
| + |
| + if (!err && !list_empty(&pagelist)) { |
| nr_failed |= migrate_pages(&pagelist, |
| alloc_migration_target_by_mpol, NULL, |
| (unsigned long)&mmpol, MIGRATE_SYNC, |
| _ |