[PATCH v5 01/28] mm: mempolicy: fix interleave index for unaligned VMA start
From: Michael S. Tsirkin
Date: Thu May 07 2026 - 18:22:45 EST
The NUMA interleave index formula (addr - vm_start) >> shift
gives wrong results when vm_start is not aligned to the folio
size: the subtraction before the shift allows low bits to
affect the result via borrows.
Use (addr >> shift) - (vm_start >> shift) instead, which
independently aligns both values before computing the
difference.
No functional change for current callers: the fix only affects
NUMA interleave and weighted-interleave policies. The only current
large-order caller is drm_pagemap which does not use NUMA
interleave. All other callers use order 0 where the old and new
formulas are equivalent. However subsequent patches in this series
add large-order callers that pass unaligned fault addresses,
making this fix necessary.
Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx>
---
mm/mempolicy.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index f0f85c89da82..583b64f2b4d3 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -2043,7 +2043,8 @@ struct mempolicy *get_vma_policy(struct vm_area_struct *vma,
if (pol->mode == MPOL_INTERLEAVE ||
pol->mode == MPOL_WEIGHTED_INTERLEAVE) {
*ilx += vma->vm_pgoff >> order;
- *ilx += (addr - vma->vm_start) >> (PAGE_SHIFT + order);
+ *ilx += (addr >> (PAGE_SHIFT + order)) -
+ (vma->vm_start >> (PAGE_SHIFT + order));
}
return pol;
}
--
MST