[PATCH 3/3] affs: validate the allocation goal in affs_alloc_block()
From: Hui Peng
Date: Sat Sep 19 2026 - 14:10:54 EST
affs_alloc_block() applies the same too-permissive range test that
affs_free_block() did, and then performs the same arithmetic:
if (!goal || goal > sbi->s_partition_size) {
...
goal = sbi->s_reserved;
}
blk = goal - sbi->s_reserved;
bmap = blk / sbi->s_bmap_bits;
bm = &sbi->s_bitmap[bmap];
if (bm->bm_free)
A goal strictly between 0 and s_reserved passes the test, underflows the
subtraction and indexes sbi->s_bitmap far out of bounds, and a goal equal
to s_partition_size overruns it by one entry.
Unlike the free path this is not driven directly by on-disk data - goal
is derived from inode state (i_lastalloc, the last allocated block, or
0) - and I have no reproducer for it. It is the same defect in the
sibling function though, so fix it the same way, with the helper that
already defines the valid block range.
Keep the `if (goal)` guard around the warning so that a first allocation
with goal == 0, which is the normal case, stays silent.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@xxxxxxxxx>
---
Behaviour change worth noting: goal == 0 previously took this branch via
the `!goal` test and now takes it via affs_validblock() returning false
(0 < s_reserved for any mountable image, since the root block alone puts
s_reserved at 2). The outcome, goal = sbi->s_reserved, is identical.
No reproducer for this one - please treat it as hardening rather than a
security fix, and drop the Fixes: tag if you would rather it did not go
to stable on its own.
diff --git a/fs/affs/bitmap.c b/fs/affs/bitmap.c
--- a/fs/affs/bitmap.c
+++ b/fs/affs/bitmap.c
@@ -133,7 +133,7 @@
return ++AFFS_I(inode)->i_lastalloc;
}
- if (!goal || goal > sbi->s_partition_size) {
+ if (!affs_validblock(sb, goal)) {
if (goal)
affs_warning(sb, "affs_balloc", "invalid goal %d", goal);
//if (!AFFS_I(inode)->i_last_block)
--
2.43.0