[PATCH 46/46] fs/proc/task_mmu: refuse addresses beyond 32 bits on 32bit
From: David Hildenbrand (Arm)
Date: Mon Oct 26 2026 - 19:39:17 EST
From: Josef Bacik <josef@xxxxxxxxxxxxxx>
The addresses in struct pm_scan_arg are 64 bits wide. The first thing
pagemap_scan_get_args() does with them is to cast them to unsigned
long. On a 32-bit kernel the upper half is dropped without a word:
PAGEMAP_SCAN of 0x100001000-0x100002000 scans, and with
PM_SCAN_WP_MATCHING write-protects, 0x1000-0x2000, stores the result
at the lower half of vec, and reports success.
Return -EFAULT, as for other addresses outside of the address space.
This is probably not worth CCing stable.
Fix generated by an LLM and sent by Josef Bacik in private.
Fixes: 52526ca7fdb9 ("fs/proc/task_mmu: implement IOCTL to get and optionally clear info about PTEs")
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
Acked-by: Lorenzo Stoakes (ARM) <ljs@xxxxxxxxxx>
Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
---
fs/proc/task_mmu.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 7452b695fdaec..762b6dbb81e4a 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -3032,6 +3032,12 @@ static int pagemap_scan_get_args(struct pm_scan_arg *arg,
arg->category_anyof_mask | arg->return_mask) & ~PM_SCAN_CATEGORIES)
return -EINVAL;
+ /* Don't cut 64-bit numbers down to addresses that happen to work. */
+ if (arg->start != (unsigned long)arg->start ||
+ arg->end != (unsigned long)arg->end ||
+ arg->vec != (unsigned long)arg->vec)
+ return -EFAULT;
+
arg->start = untagged_addr((unsigned long)arg->start);
arg->end = untagged_addr((unsigned long)arg->end);
arg->vec = untagged_addr((unsigned long)arg->vec);
--
2.43.0