* [RFC PATCH v1.1 1/7] mm/damon/core: initialize damos->last_applied
2026-07-17 14:34 [RFC PATCH v1.1 0/7] mm/damon: fix uninitialized DAMOS field and kunit exec expectation bugs SJ Park
@ 2026-07-17 14:34 ` SJ Park
2026-07-17 14:34 ` [RFC PATCH v1.1 2/7] mm/damon/core-kunit: check region count before testing in split_at() SJ Park
` (5 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:34 UTC (permalink / raw)
Cc: SJ Park, stable, Andrew Morton, Brendan Higgins, David Gow, damon,
kunit-dev, linux-kernel, linux-kselftest, linux-mm
Multiple DAMON regions could exist across a folio. If they fulfill the
condition to apply a DAMOS scheme, the scheme could be applied multiple
times to the folio. To avoid this, each DAMOS scheme stores the folio
that the scheme was applied to last time in the damos->last_applied
field and skips repeatedly applying the same scheme to the same folio.
The field is being used without initialization, though. Hence, the
mechanism could wrongly skip applying a scheme to a folio at the very
first time of DAMOS run.
The user impact is trivial. DAMON might unexpectedly skip applying
DAMOS action for one folio for the first time per scheme. In the
DAMON's best-effort world, this is never a real problem. No critical
consequences such as kernel panic or memory corruption happen.
It is a clear bug, though, and the fix is straightforward. Fix the
issue by initializing the field in DAMOS scheme creation function,
damon_new_scheme().
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/20260714055436.120034-1-sj@kernel.org
Fixes: 94ba17adaba0 ("mm/damon: avoid applying DAMOS action to same entity multiple times")
Cc: <stable@vger.kernel.org> # 6.15.x
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index f464b4f0976c3..60255f5cd715e 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -705,6 +705,7 @@ struct damos *damon_new_scheme(struct damos_access_pattern *pattern,
INIT_LIST_HEAD(&scheme->ops_filters);
scheme->stat = (struct damos_stat){};
scheme->max_nr_snapshots = 0;
+ scheme->last_applied = NULL;
INIT_LIST_HEAD(&scheme->list);
scheme->quota = *(damos_quota_init(quota));
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* [RFC PATCH v1.1 2/7] mm/damon/core-kunit: check region count before testing in split_at()
2026-07-17 14:34 [RFC PATCH v1.1 0/7] mm/damon: fix uninitialized DAMOS field and kunit exec expectation bugs SJ Park
2026-07-17 14:34 ` [RFC PATCH v1.1 1/7] mm/damon/core: initialize damos->last_applied SJ Park
@ 2026-07-17 14:34 ` SJ Park
2026-07-17 14:51 ` sashiko-bot
2026-07-17 14:34 ` [RFC PATCH v1.1 3/7] mm/damon/vaddr-kunit: check region count in three_regions test SJ Park
` (4 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:34 UTC (permalink / raw)
Cc: SJ Park, stable, Andrew Morton, Brendan Higgins, David Gow,
SeongJae Park, damon, kunit-dev, linux-kernel, linux-kselftest,
linux-mm
damon_test_split_at() test next region that is assumed to be created by
damon_split_region_at() invocation. But the split might fail. In this
case, the succeeding test may dereference invalid pointers returned by
damon_next_region().
The invalid pointer may not cause a really bad user impact, because of
the implementation detail. It would only read wrong contents in the
belonging damon_target struct. Depending on the future change of the
offset from the link header to the accessing field, this could also be
really dangerous, though. Still, the realistic user impact would be
limited. It would affect only test run setups.
Fix it by testing if the number of regions was also changed as expected
and exit early for the failure.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/20260714142352.100478-1-sj@kernel.org
Fixes: 17ccae8bb5c9 ("mm/damon: add kunit tests")
Cc: <stable@vger.kernel.org> # 5.15.x
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/tests/core-kunit.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index eba643762132f..322a295ac2cec 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -155,6 +155,10 @@ static void damon_test_split_at(struct kunit *test)
r->age = 10;
damon_add_region(r, t);
damon_split_region_at(t, r, 25);
+ KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
+ if (damon_nr_regions(t) != 2)
+ goto out;
+
KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
KUNIT_EXPECT_EQ(test, r->ar.end, 25ul);
@@ -166,6 +170,7 @@ static void damon_test_split_at(struct kunit *test)
KUNIT_EXPECT_EQ(test, r->last_nr_accesses, r_new->last_nr_accesses);
KUNIT_EXPECT_EQ(test, r->age, r_new->age);
+out:
damon_free_target(t);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1.1 2/7] mm/damon/core-kunit: check region count before testing in split_at()
2026-07-17 14:34 ` [RFC PATCH v1.1 2/7] mm/damon/core-kunit: check region count before testing in split_at() SJ Park
@ 2026-07-17 14:51 ` sashiko-bot
2026-07-17 14:54 ` SJ Park
0 siblings, 1 reply; 14+ messages in thread
From: sashiko-bot @ 2026-07-17 14:51 UTC (permalink / raw)
To: SJ Park; +Cc: damon
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Severe out-of-bounds slab write and infinite kernel loop in `damon_apply_min_nr_regions()` due to unchecked `damon_split_region_at()` failures.
--
--- Patch [2]: [RFC PATCH v1.1 2/7] mm/damon/core-kunit: check region count before testing in split_at() ---
commit d2fdc98cf0d62ffe11b7dca50c29ff7c72e1fcd6
Author: SJ Park <sj@kernel.org>
mm/damon/core-kunit: check region count before testing in split_at()
This commit fixes a potential invalid pointer dereference in the kunit tests
by checking if the region count changed as expected after a split attempt.
Since region splits can fail, it ensures the test exits early rather than
accessing an invalid next region.
Link: https://lore.kernel.org/20260714142352.100478-1-sj@kernel.org
> diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
> index eba643762132f..322a295ac2cec 100644
> --- a/mm/damon/tests/core-kunit.h
> +++ b/mm/damon/tests/core-kunit.h
> @@ -155,6 +155,10 @@ static void damon_test_split_at(struct kunit *test)
> r->age = 10;
> damon_add_region(r, t);
> damon_split_region_at(t, r, 25);
> + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
> + if (damon_nr_regions(t) != 2)
> + goto out;
> +
[Severity: Critical]
This is a pre-existing issue, but since this patch correctly notes that
damon_split_region_at() can fail, does the same unhandled failure cause an
out-of-bounds access in the core code?
Looking at mm/damon/core.c:damon_apply_min_nr_regions():
while (damon_sz_region(r) > max_region_sz) {
damon_split_region_at(t, r, max_region_sz);
r = damon_next_region(r);
}
If damon_split_region_at() fails to allocate a sub-region under memory
pressure, it silently returns. The loop then unconditionally executes
r = damon_next_region(r). Since no new sub-region was created, it skips the
remainder of the original region and advances to the next one.
If this happens on the last region in the list, r evaluates to the list head
at &t->regions_list, pushing the region pointer out-of-bounds to
(char *)t - 24. The loop would then read garbage bytes for the region
boundaries.
If those garbage bytes evaluate to a size greater than max_region_sz, could
it call damon_split_region_at() again on this invalid pointer? If a
subsequent allocation succeeds, r->ar.end = new->ar.start could write a
user-monitored address into the out-of-bounds slab memory, potentially
corrupting memory 16 bytes before the damon_target object.
Additionally, if allocations consistently fail, could the fake region's next
pointer wrap back to the first valid region and create an unbreakable infinite
loop in the kdamond thread?
> KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
> KUNIT_EXPECT_EQ(test, r->ar.end, 25ul);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260717143445.91207-1-sj@kernel.org?part=2
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1.1 2/7] mm/damon/core-kunit: check region count before testing in split_at()
2026-07-17 14:51 ` sashiko-bot
@ 2026-07-17 14:54 ` SJ Park
0 siblings, 0 replies; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:54 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, damon
On Fri, 17 Jul 2026 14:51:56 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [Critical] Severe out-of-bounds slab write and infinite kernel loop in `damon_apply_min_nr_regions()` due to unchecked `damon_split_region_at()` failures.
> --
>
> --- Patch [2]: [RFC PATCH v1.1 2/7] mm/damon/core-kunit: check region count before testing in split_at() ---
> commit d2fdc98cf0d62ffe11b7dca50c29ff7c72e1fcd6
> Author: SJ Park <sj@kernel.org>
>
> mm/damon/core-kunit: check region count before testing in split_at()
>
> This commit fixes a potential invalid pointer dereference in the kunit tests
> by checking if the region count changed as expected after a split attempt.
> Since region splits can fail, it ensures the test exits early rather than
> accessing an invalid next region.
>
> Link: https://lore.kernel.org/20260714142352.100478-1-sj@kernel.org
>
> > diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
> > index eba643762132f..322a295ac2cec 100644
> > --- a/mm/damon/tests/core-kunit.h
> > +++ b/mm/damon/tests/core-kunit.h
> > @@ -155,6 +155,10 @@ static void damon_test_split_at(struct kunit *test)
> > r->age = 10;
> > damon_add_region(r, t);
> > damon_split_region_at(t, r, 25);
> > + KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
> > + if (damon_nr_regions(t) != 2)
> > + goto out;
> > +
>
> [Severity: Critical]
> This is a pre-existing issue, but since this patch correctly notes that
> damon_split_region_at() can fail, does the same unhandled failure cause an
> out-of-bounds access in the core code?
>
> Looking at mm/damon/core.c:damon_apply_min_nr_regions():
>
> while (damon_sz_region(r) > max_region_sz) {
> damon_split_region_at(t, r, max_region_sz);
> r = damon_next_region(r);
> }
>
> If damon_split_region_at() fails to allocate a sub-region under memory
> pressure, it silently returns. The loop then unconditionally executes
> r = damon_next_region(r). Since no new sub-region was created, it skips the
> remainder of the original region and advances to the next one.
>
> If this happens on the last region in the list, r evaluates to the list head
> at &t->regions_list, pushing the region pointer out-of-bounds to
> (char *)t - 24. The loop would then read garbage bytes for the region
> boundaries.
>
> If those garbage bytes evaluate to a size greater than max_region_sz, could
> it call damon_split_region_at() again on this invalid pointer? If a
> subsequent allocation succeeds, r->ar.end = new->ar.start could write a
> user-monitored address into the out-of-bounds slab memory, potentially
> corrupting memory 16 bytes before the damon_target object.
>
> Additionally, if allocations consistently fail, could the fake region's next
> pointer wrap back to the first valid region and create an unbreakable infinite
> loop in the kdamond thread?
This is a known issue that I'm separately working on.
>
> > KUNIT_EXPECT_EQ(test, r->ar.start, 0ul);
> > KUNIT_EXPECT_EQ(test, r->ar.end, 25ul);
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260717143445.91207-1-sj@kernel.org?part=2
Thanks,
SJ
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH v1.1 3/7] mm/damon/vaddr-kunit: check region count in three_regions test
2026-07-17 14:34 [RFC PATCH v1.1 0/7] mm/damon: fix uninitialized DAMOS field and kunit exec expectation bugs SJ Park
2026-07-17 14:34 ` [RFC PATCH v1.1 1/7] mm/damon/core: initialize damos->last_applied SJ Park
2026-07-17 14:34 ` [RFC PATCH v1.1 2/7] mm/damon/core-kunit: check region count before testing in split_at() SJ Park
@ 2026-07-17 14:34 ` SJ Park
2026-07-17 14:50 ` sashiko-bot
2026-07-17 14:34 ` [RFC PATCH v1.1 4/7] mm/damon/core-kunit: handle region split failure in filter_out() SJ Park
` (3 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:34 UTC (permalink / raw)
Cc: SJ Park, stable, Andrew Morton, Brendan Higgins, David Gow,
SeongJae Park, damon, kunit-dev, linux-kernel, linux-kselftest,
linux-mm
damon_do_test_apply_three_regions() iterates regions after
damon_set_regions() call assuming the function would succeed at setting
the number of regions the same to the expected one. It might have
failed. In this case, __nth_region_of() in the iteration could return
NULL and NULL dereference can happen in the test.
The consequent user impact (NULL dereference) is quite bad. The
realistic user impact would be limited, though. It would affect only
test run setups.
Fix it by testing if the number of regions was also changed as expected
and exit early for the failure.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/20260713144757.39740-1-sj@kernel.org
Fixes: 17ccae8bb5c9 ("mm/damon: add kunit tests")
Cc: <stable@vger.kernel.org> # 5.15.x
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/tests/vaddr-kunit.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/mm/damon/tests/vaddr-kunit.h b/mm/damon/tests/vaddr-kunit.h
index 61f844336ffb5..6a95441d193ae 100644
--- a/mm/damon/tests/vaddr-kunit.h
+++ b/mm/damon/tests/vaddr-kunit.h
@@ -158,12 +158,17 @@ static void damon_do_test_apply_three_regions(struct kunit *test,
kunit_skip(test, "second damon_set_regions() fail");
}
+ KUNIT_EXPECT_EQ(test, damon_nr_regions(t), nr_expected / 2);
+ if (damon_nr_regions(t) != nr_expected / 2)
+ goto out;
+
for (i = 0; i < nr_expected / 2; i++) {
r = __nth_region_of(t, i);
KUNIT_EXPECT_EQ(test, r->ar.start, expected[i * 2]);
KUNIT_EXPECT_EQ(test, r->ar.end, expected[i * 2 + 1]);
}
+out:
damon_destroy_target(t, NULL);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1.1 3/7] mm/damon/vaddr-kunit: check region count in three_regions test
2026-07-17 14:34 ` [RFC PATCH v1.1 3/7] mm/damon/vaddr-kunit: check region count in three_regions test SJ Park
@ 2026-07-17 14:50 ` sashiko-bot
2026-07-17 14:55 ` SJ Park
0 siblings, 1 reply; 14+ messages in thread
From: sashiko-bot @ 2026-07-17 14:50 UTC (permalink / raw)
To: SJ Park; +Cc: damon
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Out-of-bounds array read in KUnit test helpers due to missing array bounds check and ignored return values
--
--- Patch [3]: [RFC PATCH v1.1 3/7] mm/damon/vaddr-kunit: check region count in three_regions test ---
commit b2d38d564a3004fa6df02a9f1d54af3423302437
Author: SJ Park <sj@kernel.org>
mm/damon/vaddr-kunit: check region count in three_regions test
This commit adds a check in damon_do_test_apply_three_regions() to ensure
damon_set_regions() succeeded in setting the expected number of regions.
This prevents a potential NULL pointer dereference during test iteration.
Link: https://lore.kernel.org/20260713144757.39740-1-sj@kernel.org
> diff --git a/mm/damon/tests/vaddr-kunit.h b/mm/damon/tests/vaddr-kunit.h
> index 61f844336ffb5..6a95441d193ae 100644
> --- a/mm/damon/tests/vaddr-kunit.h
> +++ b/mm/damon/tests/vaddr-kunit.h
[ ... ]
[Severity: High]
This is a pre-existing issue, but while reviewing this test fix, I noticed
similar missing bounds checks and unhandled return values in
mm/damon/tests/core-kunit.h that can cause out-of-bounds array reads.
In damon_test_commit_target_regions_for():
damon_commit_target_regions(dst_target, src_target, 1);
i = 0;
damon_for_each_region(r, dst_target) {
KUNIT_EXPECT_EQ(test, r->ar.start, expect_start_end[i][0]);
KUNIT_EXPECT_EQ(test, r->ar.end, expect_start_end[i][1]);
i++;
}
If memory allocation fails inside damon_commit_target_regions(), it returns
an error without modifying dst_target. Because the return value is ignored
here, could this iterate over the original regions of dst_target and read
past the end of the expect_start_end stack array?
A similar pattern appears in damos_test_commit_quota_goals_for():
damos_commit_quota_goals(&dst, &src);
i = 0;
damos_for_each_quota_goal(goal, (&dst)) {
KUNIT_EXPECT_EQ(test, goal->metric, src_goals[i].metric);
KUNIT_EXPECT_EQ(test, goal->target_value,
src_goals[i++].target_value);
}
Does ignoring the return value of damos_commit_quota_goals() risk an
out-of-bounds read on src_goals[] if the destination goals are not updated
and retain more items than expected?
Finally, in damos_test_commit_dests_for():
KUNIT_EXPECT_EQ(test, dst.nr_dests, src_nr_dests);
for (i = 0; i < dst.nr_dests; i++) {
KUNIT_EXPECT_EQ(test, dst.node_id_arr[i], src_node_id_arr[i]);
KUNIT_EXPECT_EQ(test, dst.weight_arr[i], src_weight_arr[i]);
}
Since KUNIT_EXPECT_EQ does not abort test execution on failure, could an
out-of-bounds read occur on src_node_id_arr[] and src_weight_arr[] if
dst.nr_dests ends up larger than src_nr_dests?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260717143445.91207-1-sj@kernel.org?part=3
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1.1 3/7] mm/damon/vaddr-kunit: check region count in three_regions test
2026-07-17 14:50 ` sashiko-bot
@ 2026-07-17 14:55 ` SJ Park
0 siblings, 0 replies; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:55 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, damon
On Fri, 17 Jul 2026 14:50:49 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] Out-of-bounds array read in KUnit test helpers due to missing array bounds check and ignored return values
> --
>
> --- Patch [3]: [RFC PATCH v1.1 3/7] mm/damon/vaddr-kunit: check region count in three_regions test ---
> commit b2d38d564a3004fa6df02a9f1d54af3423302437
> Author: SJ Park <sj@kernel.org>
>
> mm/damon/vaddr-kunit: check region count in three_regions test
>
> This commit adds a check in damon_do_test_apply_three_regions() to ensure
> damon_set_regions() succeeded in setting the expected number of regions.
> This prevents a potential NULL pointer dereference during test iteration.
>
> Link: https://lore.kernel.org/20260713144757.39740-1-sj@kernel.org
>
> > diff --git a/mm/damon/tests/vaddr-kunit.h b/mm/damon/tests/vaddr-kunit.h
> > index 61f844336ffb5..6a95441d193ae 100644
> > --- a/mm/damon/tests/vaddr-kunit.h
> > +++ b/mm/damon/tests/vaddr-kunit.h
>
> [ ... ]
>
> [Severity: High]
> This is a pre-existing issue, but while reviewing this test fix, I noticed
> similar missing bounds checks and unhandled return values in
> mm/damon/tests/core-kunit.h that can cause out-of-bounds array reads.
>
> In damon_test_commit_target_regions_for():
>
> damon_commit_target_regions(dst_target, src_target, 1);
> i = 0;
> damon_for_each_region(r, dst_target) {
> KUNIT_EXPECT_EQ(test, r->ar.start, expect_start_end[i][0]);
> KUNIT_EXPECT_EQ(test, r->ar.end, expect_start_end[i][1]);
> i++;
> }
>
> If memory allocation fails inside damon_commit_target_regions(), it returns
> an error without modifying dst_target. Because the return value is ignored
> here, could this iterate over the original regions of dst_target and read
> past the end of the expect_start_end stack array?
>
> A similar pattern appears in damos_test_commit_quota_goals_for():
>
> damos_commit_quota_goals(&dst, &src);
>
> i = 0;
> damos_for_each_quota_goal(goal, (&dst)) {
> KUNIT_EXPECT_EQ(test, goal->metric, src_goals[i].metric);
> KUNIT_EXPECT_EQ(test, goal->target_value,
> src_goals[i++].target_value);
> }
>
> Does ignoring the return value of damos_commit_quota_goals() risk an
> out-of-bounds read on src_goals[] if the destination goals are not updated
> and retain more items than expected?
>
> Finally, in damos_test_commit_dests_for():
>
> KUNIT_EXPECT_EQ(test, dst.nr_dests, src_nr_dests);
> for (i = 0; i < dst.nr_dests; i++) {
> KUNIT_EXPECT_EQ(test, dst.node_id_arr[i], src_node_id_arr[i]);
> KUNIT_EXPECT_EQ(test, dst.weight_arr[i], src_weight_arr[i]);
> }
>
> Since KUNIT_EXPECT_EQ does not abort test execution on failure, could an
> out-of-bounds read occur on src_node_id_arr[] and src_weight_arr[] if
> dst.nr_dests ends up larger than src_nr_dests?
These issues are fixed by other patches in this series.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260717143445.91207-1-sj@kernel.org?part=3
Thanks,
SJ
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH v1.1 4/7] mm/damon/core-kunit: handle region split failure in filter_out()
2026-07-17 14:34 [RFC PATCH v1.1 0/7] mm/damon: fix uninitialized DAMOS field and kunit exec expectation bugs SJ Park
` (2 preceding siblings ...)
2026-07-17 14:34 ` [RFC PATCH v1.1 3/7] mm/damon/vaddr-kunit: check region count in three_regions test SJ Park
@ 2026-07-17 14:34 ` SJ Park
2026-07-17 14:49 ` sashiko-bot
2026-07-17 14:34 ` [RFC PATCH v1.1 5/7] mm/damon/core-kunit: skip wrong dest walk in commit_dests_for() SJ Park
` (2 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:34 UTC (permalink / raw)
Cc: SJ Park, stable, Andrew Morton, Brendan Higgins, David Gow, damon,
kunit-dev, linux-kernel, linux-kselftest, linux-mm
dasmon_test_filter_out() test checks if damos_filter_match() of an
address filter splits the region as expected under a given condition.
But, the test continued regardless of the split successes. As a result,
the later part of the test could dereference invalid pointers that
returned from damon_next_region(). Further, it could corrupt memory
from damon_destroy_region().
The consequent user impact (memory corruption) is quite bad. The
realistic user impact would be limited, though. It would affect only
test run setups.
Fix it by exiting early for the number of regions test failure.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/20260714142352.100478-1-sj@kernel.org
Fixes: 26713c890875 ("mm/damon/core-test: add a unit test for __damos_filter_out()")
Cc: <stable@vger.kernel.org> # 6.6.x
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/tests/core-kunit.h | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index 322a295ac2cec..eddf3a0484583 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -1365,6 +1365,8 @@ static void damos_test_filter_out(struct kunit *test)
KUNIT_EXPECT_EQ(test, r->ar.start, 1);
KUNIT_EXPECT_EQ(test, r->ar.end, 2);
KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
+ if (damon_nr_regions(t) != 2)
+ goto out;
r2 = damon_next_region(r);
KUNIT_EXPECT_EQ(test, r2->ar.start, 2);
KUNIT_EXPECT_EQ(test, r2->ar.end, 4);
@@ -1379,11 +1381,14 @@ static void damos_test_filter_out(struct kunit *test)
KUNIT_EXPECT_EQ(test, r->ar.start, 2);
KUNIT_EXPECT_EQ(test, r->ar.end, 6);
KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
+ if (damon_nr_regions(t) != 2)
+ goto out;
r2 = damon_next_region(r);
KUNIT_EXPECT_EQ(test, r2->ar.start, 6);
KUNIT_EXPECT_EQ(test, r2->ar.end, 8);
damon_destroy_region(r2, t);
+out:
damon_free_target(t);
damos_free_filter(f);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1.1 4/7] mm/damon/core-kunit: handle region split failure in filter_out()
2026-07-17 14:34 ` [RFC PATCH v1.1 4/7] mm/damon/core-kunit: handle region split failure in filter_out() SJ Park
@ 2026-07-17 14:49 ` sashiko-bot
2026-07-17 14:56 ` SJ Park
0 siblings, 1 reply; 14+ messages in thread
From: sashiko-bot @ 2026-07-17 14:49 UTC (permalink / raw)
To: SJ Park; +Cc: damon
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but it shares the exact same logic flaw fixed here. In `damon_apply_min_nr_regions()`, if `damon_split_region_at()` fails to allocate a new region (e.g., due to memory pressure), it leaves `r` unmodified. However, the inner `while` loop unconditionally executes `r = damon_next_region(r);`. If `r` was the last region in the list, `damon_next_region(r)` will return a pointer derived from the list head (`&t->regions_list`), resulting in a fake `damon_region` pointer pointing into the middle of the `damon_target` struct or preceding memory. The loop then evaluates `damon_sz_region(r)` on this fake region, reading garbage memory. If the garbage evaluates to a size greater than `max_region_sz`, it will invoke `damon_split_region_at()` on the fake region, causing an out-of-bounds write and list corruption (overwriting `r_fake->ar.end` and `t->regions_list`), or an infinite loop lockup if allocations keep failing.
--
--- Patch [4]: [RFC PATCH v1.1 4/7] mm/damon/core-kunit: handle region split failure in filter_out() ---
commit 571c1400b8cb843c3acdb1ded0915fd9807f302f
Author: SJ Park <sj@kernel.org>
mm/damon/core-kunit: handle region split failure in filter_out()
This commit fixes a bug in the DAMON kunit tests where test execution
continued even if a region failed to split as expected. By exiting early
when the number of regions does not match expectations, it prevents
dereferencing invalid pointers and potential memory corruption.
Link: https://lore.kernel.org/20260714142352.100478-1-sj@kernel.org
> diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
> index 322a295ac2cec..eddf3a0484583 100644
> --- a/mm/damon/tests/core-kunit.h
> +++ b/mm/damon/tests/core-kunit.h
> @@ -1365,6 +1365,8 @@ static void damos_test_filter_out(struct kunit *test)
> KUNIT_EXPECT_EQ(test, r->ar.start, 1);
> KUNIT_EXPECT_EQ(test, r->ar.end, 2);
> KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
> + if (damon_nr_regions(t) != 2)
> + goto out;
[Severity: High]
This isn't a bug introduced by this patch, but it shares the exact same logic
flaw fixed here.
In mm/damon/core.c:damon_apply_min_nr_regions():
damon_for_each_region_safe(r, next, t) {
while (damon_sz_region(r) > max_region_sz) {
damon_split_region_at(t, r, max_region_sz);
r = damon_next_region(r);
}
}
If damon_split_region_at() fails to allocate a new region (e.g., due to memory
pressure), it leaves r unmodified. However, the inner while loop
unconditionally executes r = damon_next_region(r).
If r was the last region in the list, damon_next_region(r) will return a
pointer derived from the list head (&t->regions_list), resulting in a fake
damon_region pointer. The loop then evaluates damon_sz_region(r) on this fake
region, reading garbage memory.
If the garbage evaluates to a size greater than max_region_sz, it will invoke
damon_split_region_at() on the fake region.
Can this lead to an out-of-bounds write and list corruption, or an infinite
loop lockup if allocations keep failing?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260717143445.91207-1-sj@kernel.org?part=4
^ permalink raw reply [flat|nested] 14+ messages in thread* Re: [RFC PATCH v1.1 4/7] mm/damon/core-kunit: handle region split failure in filter_out()
2026-07-17 14:49 ` sashiko-bot
@ 2026-07-17 14:56 ` SJ Park
0 siblings, 0 replies; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:56 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, damon
On Fri, 17 Jul 2026 14:49:04 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [High] This problem wasn't introduced by this patch, but it shares the exact same logic flaw fixed here. In `damon_apply_min_nr_regions()`, if `damon_split_region_at()` fails to allocate a new region (e.g., due to memory pressure), it leaves `r` unmodified. However, the inner `while` loop unconditionally executes `r = damon_next_region(r);`. If `r` was the last region in the list, `damon_next_region(r)` will return a pointer derived from the list head (`&t->regions_list`), resulting in a fake `damon_region` pointer pointing into the middle of the `damon_target` struct or preceding memory. The loop then evaluates `damon_sz_region(r)` on this fake region, reading garbage memory. If the garbage evaluates to a size greater than `max_region_sz`, it will invoke `damon_split_region_at()` on the fake region, causing an out-of-bounds write and list corruption (overwriting `r_fake->ar.end` and `t->regions_list`), or an infinite loop lockup if allocations keep failing.
> --
>
> --- Patch [4]: [RFC PATCH v1.1 4/7] mm/damon/core-kunit: handle region split failure in filter_out() ---
> commit 571c1400b8cb843c3acdb1ded0915fd9807f302f
> Author: SJ Park <sj@kernel.org>
>
> mm/damon/core-kunit: handle region split failure in filter_out()
>
> This commit fixes a bug in the DAMON kunit tests where test execution
> continued even if a region failed to split as expected. By exiting early
> when the number of regions does not match expectations, it prevents
> dereferencing invalid pointers and potential memory corruption.
>
> Link: https://lore.kernel.org/20260714142352.100478-1-sj@kernel.org
>
> > diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
> > index 322a295ac2cec..eddf3a0484583 100644
> > --- a/mm/damon/tests/core-kunit.h
> > +++ b/mm/damon/tests/core-kunit.h
> > @@ -1365,6 +1365,8 @@ static void damos_test_filter_out(struct kunit *test)
> > KUNIT_EXPECT_EQ(test, r->ar.start, 1);
> > KUNIT_EXPECT_EQ(test, r->ar.end, 2);
> > KUNIT_EXPECT_EQ(test, damon_nr_regions(t), 2);
> > + if (damon_nr_regions(t) != 2)
> > + goto out;
>
> [Severity: High]
> This isn't a bug introduced by this patch, but it shares the exact same logic
> flaw fixed here.
>
> In mm/damon/core.c:damon_apply_min_nr_regions():
>
> damon_for_each_region_safe(r, next, t) {
> while (damon_sz_region(r) > max_region_sz) {
> damon_split_region_at(t, r, max_region_sz);
> r = damon_next_region(r);
> }
> }
>
> If damon_split_region_at() fails to allocate a new region (e.g., due to memory
> pressure), it leaves r unmodified. However, the inner while loop
> unconditionally executes r = damon_next_region(r).
>
> If r was the last region in the list, damon_next_region(r) will return a
> pointer derived from the list head (&t->regions_list), resulting in a fake
> damon_region pointer. The loop then evaluates damon_sz_region(r) on this fake
> region, reading garbage memory.
>
> If the garbage evaluates to a size greater than max_region_sz, it will invoke
> damon_split_region_at() on the fake region.
>
> Can this lead to an out-of-bounds write and list corruption, or an infinite
> loop lockup if allocations keep failing?
This is a known issue that I'm separately working on.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260717143445.91207-1-sj@kernel.org?part=4
Thanks,
SJ
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH v1.1 5/7] mm/damon/core-kunit: skip wrong dest walk in commit_dests_for()
2026-07-17 14:34 [RFC PATCH v1.1 0/7] mm/damon: fix uninitialized DAMOS field and kunit exec expectation bugs SJ Park
` (3 preceding siblings ...)
2026-07-17 14:34 ` [RFC PATCH v1.1 4/7] mm/damon/core-kunit: handle region split failure in filter_out() SJ Park
@ 2026-07-17 14:34 ` SJ Park
2026-07-17 14:34 ` [RFC PATCH v1.1 6/7] mm/damon/core-kunit: skip wrong quota goal walk in commit_quota_goals() SJ Park
2026-07-17 14:34 ` [RFC PATCH v1.1 7/7] mm/damon/core-kunit: skip wrong region walk in commit_target_regions() SJ Park
6 siblings, 0 replies; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:34 UTC (permalink / raw)
Cc: SJ Park, stable, Andrew Morton, Brendan Higgins, David Gow, damon,
kunit-dev, linux-kernel, linux-kselftest, linux-mm
damos_test_commit_dests_for() traverse damos action destinations after
damos_commit_dests(). It assumes damos_commit_dests() made expected
numbers of destinations for source and destination structures. It might
not. Because the traversal is made based on destination struct length,
it could do out of bounds access for source value expectation.
The consequent user impact (out-of-bound access ) is quite bad. The
realistic user impact would be limited, though. It would affect only
test run setups.
Fix it by exiting early for the number of regions test failure.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/20260713144757.39740-1-sj@kernel.org
Fixes: eec573b8dd65 ("mm/damon/tests/core-kunit: add damos_commit_dests() test")
Cc: <stable@vger.kernel.org> # 6.19.x
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/tests/core-kunit.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index eddf3a0484583..9b8c20a50ad53 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -1008,6 +1008,8 @@ static void damos_test_commit_dests_for(struct kunit *test,
skip = false;
KUNIT_EXPECT_EQ(test, dst.nr_dests, src_nr_dests);
+ if (dst.nr_dests != src_nr_dests)
+ goto out;
for (i = 0; i < dst.nr_dests; i++) {
KUNIT_EXPECT_EQ(test, dst.node_id_arr[i], src_node_id_arr[i]);
KUNIT_EXPECT_EQ(test, dst.weight_arr[i], src_weight_arr[i]);
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* [RFC PATCH v1.1 6/7] mm/damon/core-kunit: skip wrong quota goal walk in commit_quota_goals()
2026-07-17 14:34 [RFC PATCH v1.1 0/7] mm/damon: fix uninitialized DAMOS field and kunit exec expectation bugs SJ Park
` (4 preceding siblings ...)
2026-07-17 14:34 ` [RFC PATCH v1.1 5/7] mm/damon/core-kunit: skip wrong dest walk in commit_dests_for() SJ Park
@ 2026-07-17 14:34 ` SJ Park
2026-07-17 14:34 ` [RFC PATCH v1.1 7/7] mm/damon/core-kunit: skip wrong region walk in commit_target_regions() SJ Park
6 siblings, 0 replies; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:34 UTC (permalink / raw)
Cc: SJ Park, stable, Andrew Morton, Brendan Higgins, David Gow, damon,
kunit-dev, linux-kernel, linux-kselftest, linux-mm
damos_test_commit_quota_goals_for() traverses damos quota goals after
damos_commit_quota_goals() call. It assumes damos_commit_quota_goals()
made expected numbers of goals. It might not. Because the traversal is
made based on destination struct length, it could do out of bounds
access for source expectation value array.
The consequent user impact (out-of-bound access ) is quite bad. The
realistic user impact would be limited though. It would affect only
test run setups.
Fix it by testing if the number of goals was also changed as expected
and exit early for the failure.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/20260713144757.39740-1-sj@kernel.org
Fixes: d9adfb8a28e7 ("mm/damon/tests/core-kunit: add damos_commit_quota_goals() test")
Cc: <stable@vger.kernel.org> # 6.19.x
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/tests/core-kunit.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index 9b8c20a50ad53..fbf986aee2dea 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -839,6 +839,7 @@ static void damos_test_commit_quota_goals_for(struct kunit *test,
struct damos_quota_goal *goal, *next;
bool skip = true;
int i;
+ int nr_dst = 0, nr_src = 0;
INIT_LIST_HEAD(&dst.goals);
INIT_LIST_HEAD(&src.goals);
@@ -861,6 +862,14 @@ static void damos_test_commit_quota_goals_for(struct kunit *test,
damos_commit_quota_goals(&dst, &src);
+ damos_for_each_quota_goal(goal, &dst)
+ nr_dst++;
+ damos_for_each_quota_goal(goal, &src)
+ nr_src++;
+ KUNIT_EXPECT_EQ(test, nr_dst, nr_src);
+ if (nr_dst != nr_src)
+ goto out;
+
i = 0;
damos_for_each_quota_goal(goal, (&dst)) {
KUNIT_EXPECT_EQ(test, goal->metric, src_goals[i].metric);
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread* [RFC PATCH v1.1 7/7] mm/damon/core-kunit: skip wrong region walk in commit_target_regions()
2026-07-17 14:34 [RFC PATCH v1.1 0/7] mm/damon: fix uninitialized DAMOS field and kunit exec expectation bugs SJ Park
` (5 preceding siblings ...)
2026-07-17 14:34 ` [RFC PATCH v1.1 6/7] mm/damon/core-kunit: skip wrong quota goal walk in commit_quota_goals() SJ Park
@ 2026-07-17 14:34 ` SJ Park
6 siblings, 0 replies; 14+ messages in thread
From: SJ Park @ 2026-07-17 14:34 UTC (permalink / raw)
Cc: SJ Park, stable, Andrew Morton, Brendan Higgins, David Gow, damon,
kunit-dev, linux-kernel, linux-kselftest, linux-mm
damon_test_commit_target_regions_for() traverses expected values array
after damon_commit_target_regions() call. It assumes
damon_commit_target_regions() made expected number of regions. It might
not. Because the traversal is made based on the region count, it could
do out of bounds access to the expectation value array.
The consequent user impact (out-of-bound access) is quite bad. The
realistic user impact would be limited, though. It would affect only
test run setups.
Fix it by testing if the number of regions was also changed as expected
and exit early for the failure.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/20260713144757.39740-1-sj@kernel.org
Fixes: 603f67eb91e0 ("mm/damon/tests/core-kunit: add damon_commit_target_regions() test")
Cc: <stable@vger.kernel.org> # 6.19.x
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/tests/core-kunit.h | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/mm/damon/tests/core-kunit.h b/mm/damon/tests/core-kunit.h
index fbf986aee2dea..4a536d41cdb2d 100644
--- a/mm/damon/tests/core-kunit.h
+++ b/mm/damon/tests/core-kunit.h
@@ -1277,14 +1277,19 @@ static void damon_test_commit_target_regions_for(struct kunit *test,
kunit_skip(test, "src target setup fail");
}
damon_commit_target_regions(dst_target, src_target, 1);
+
+ KUNIT_EXPECT_EQ(test, damon_nr_regions(dst_target), nr_expect_regions);
+ if (damon_nr_regions(dst_target) != nr_expect_regions)
+ goto out;
+
i = 0;
damon_for_each_region(r, dst_target) {
KUNIT_EXPECT_EQ(test, r->ar.start, expect_start_end[i][0]);
KUNIT_EXPECT_EQ(test, r->ar.end, expect_start_end[i][1]);
i++;
}
- KUNIT_EXPECT_EQ(test, damon_nr_regions(dst_target), nr_expect_regions);
- KUNIT_EXPECT_EQ(test, i, nr_expect_regions);
+
+out:
damon_free_target(dst_target);
damon_free_target(src_target);
}
--
2.47.3
^ permalink raw reply related [flat|nested] 14+ messages in thread