From: sashiko-bot@kernel.org
To: "SJ Park" <sj@kernel.org>
Cc: damon@lists.linux.dev
Subject: Re: [RFC PATCH 07/16] mm/damon/core: extend merge function to work with probe hits
Date: Sun, 05 Jul 2026 21:11:01 +0000 [thread overview]
Message-ID: <20260705211101.F2F061F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260705205743.98656-8-sj@kernel.org>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Incompatible scale and domain mismatch between weighted scores and unweighted merge thresholds.
- [High] Unsafe use of `abs()` macro on large unsigned integer score differences causes silent signed integer overflow.
- [Medium] Calculating the weighted sum of probe hits in `damon_probe_hits_wsum` can easily overflow a 32-bit `unsigned int`.
Pre-existing issues:
- [High] Weighted average calculations in `damon_merge_two_regions` silently overflow 32-bit `unsigned long` on 32-bit architectures.
--
commit 54d6e0bb9900e63a1a016ffee9632b6aa602175b
Author: SJ Park <sj@kernel.org>
mm/damon/core: extend merge function to work with probe hits
This commit extends damon_merge_regions_of() to consider the weighted sum
of probe hits when calculating regions to merge, introducing
damon_has_probe_weights() and modifying the scoring logic to use these weights.
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index c370eaff5795d..f6e03746b170e 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
[ ... ]
> @@ -3187,6 +3192,16 @@ static void damon_merge_two_regions(struct damon_target *t,
> damon_destroy_region(r, t);
> }
[Severity: High]
This isn't a bug introduced by this patch, but can the weighted average
calculations in damon_merge_two_regions() silently overflow a 32-bit
unsigned long on 32-bit architectures?
On 32-bit architectures, sz_l is a 32-bit unsigned long.
If the region size is large (e.g., hundreds of megabytes), multiplying sz_l
by nr_accesses or probe_hits could exceed the 4.29B maximum of a 32-bit
integer, corrupting the merged region's statistics.
mm/damon/core.c:damon_merge_two_regions() {
...
l->nr_accesses = (l->nr_accesses * sz_l + r->nr_accesses * sz_r) /
(sz_l + sz_r);
...
for (i = 0; i < DAMON_MAX_PROBES; i++)
l->probe_hits[i] = (l->probe_hits[i] * sz_l + r->probe_hits[i]
* sz_r) / (sz_l + sz_r);
...
}
> +static unsigned int damon_merge_score(struct damon_region *r, bool last,
> + struct damon_ctx *ctx, bool use_probe_hits)
> +{
> + if (use_probe_hits)
> + return damon_probe_hits_wsum(r, last, ctx);
[Severity: Medium]
Can the multiplication in damon_probe_hits_wsum() overflow a 32-bit
unsigned int?
probe->weight is an unsigned int.
If users supply a large weight, multiplying it by r->probe_hits[i] (which can
be up to 255) might exceed UINT_MAX, causing the sum to wrap around and yield
artificially small scores for highly active regions.
mm/damon/core.c:damon_probe_hits_wsum() {
...
if (last)
sum += r->last_probe_hits[i++] * probe->weight;
else
sum += r->probe_hits[i++] * probe->weight;
...
}
> + if (last)
> + return r->last_nr_accesses;
> + return r->nr_accesses;
> +}
> +
> /*
> * Merge adjacent regions having similar access frequencies
> *
> @@ -3195,24 +3210,37 @@ static void damon_merge_two_regions(struct damon_target *t,
> * sz_limit size upper limit of each region
> */
> static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
> - unsigned long sz_limit)
> + unsigned long sz_limit, struct damon_ctx *ctx)
> {
> struct damon_region *r, *prev = NULL, *next;
> + bool use_probe_hits = damon_has_probe_weights(ctx);
>
> damon_for_each_region_safe(r, next, t) {
> - if (abs(r->nr_accesses - r->last_nr_accesses) > thres)
> + unsigned int score, last_score;
> +
> + score = damon_merge_score(r, false, ctx, use_probe_hits);
> + last_score = damon_merge_score(r, true, ctx, use_probe_hits);
> +
> + if (abs(score - last_score) > thres)
[Severity: High]
Does the use of abs() here cause a silent signed integer overflow for large
unsigned differences?
The macro abs() implicitly casts an unsigned int to a signed int.
If the mathematical difference between score and last_score exceeds INT_MAX
(which might happen with large user-defined probe weights), the cast wraps to
a negative number.
The abs() macro then negates it into an artificially small positive integer,
which could cause the code to incorrectly bypass the > thres check and merge
regions with vastly different access profiles.
[Severity: High]
Is there a domain mismatch between the weighted score differences and the
unweighted thres parameter?
When use_probe_hits is true, the score is a weighted sum derived from probe
hits and user-defined weights. However, thres operates in the unweighted access
frequency domain.
This mismatch appears to carry over to kdamond_merge_regions(), where max_thres
is also scaled in the unweighted domain (aggr_interval / sample_interval).
Because weighted scores operate in a different numerical domain, could they
easily exceed max_thres, forcing the merge loop in kdamond_merge_regions() to
terminate prematurely?
mm/damon/core.c:kdamond_merge_regions() {
...
max_thres = c->attrs.aggr_interval /
(c->attrs.sample_interval ? c->attrs.sample_interval : 1);
do {
...
threshold = max(1, threshold * 2);
} while (nr_regions > c->attrs.max_nr_regions &&
threshold / 2 < max_thres);
...
}
> r->age = 0;
> - else if ((r->nr_accesses == 0) != (r->last_nr_accesses == 0))
> + else if ((score == 0) != (last_score == 0))
> r->age = 0;
> else
> r->age++;
>
> - if (prev && prev->ar.end == r->ar.start &&
> - abs(prev->nr_accesses - r->nr_accesses) <= thres &&
> - damon_sz_region(prev) + damon_sz_region(r) <= sz_limit)
> - damon_merge_two_regions(t, prev, r);
> - else
> - prev = r;
> + if (!prev)
> + goto set_prev_continue;
> + if (prev->ar.end != r->ar.start)
> + goto set_prev_continue;
> + if (abs(damon_merge_score(prev, false, ctx, use_probe_hits) -
> + score) > thres)
[Severity: High]
Does this abs() usage also suffer from the same silent signed integer overflow
as mentioned above when comparing large unsigned score differences?
> + goto set_prev_continue;
> + if (damon_sz_region(prev) + damon_sz_region(r) > sz_limit)
> + goto set_prev_continue;
> + damon_merge_two_regions(t, prev, r);
> + continue;
> +set_prev_continue:
> + prev = r;
> }
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260705205743.98656-1-sj@kernel.org?part=7
next prev parent reply other threads:[~2026-07-05 21:11 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-05 20:57 [RFC PATCH 00/16] mm/damon: introduce data attributes only monitoring SJ Park
2026-07-05 20:57 ` [RFC PATCH 01/16] mm/damon/core: introduce damon_probe->weight SJ Park
2026-07-05 21:04 ` sashiko-bot
2026-07-05 21:21 ` SJ Park
2026-07-05 20:57 ` [RFC PATCH 02/16] mm/damon/core: ask apply_probes() ops callback to set sampling address SJ Park
2026-07-05 21:07 ` sashiko-bot
2026-07-05 21:25 ` SJ Park
2026-07-05 20:57 ` [RFC PATCH 03/16] mm/damon/paddr: set samples in apply_probes() if requested SJ Park
2026-07-05 21:11 ` sashiko-bot
2026-07-05 21:28 ` SJ Park
2026-07-05 20:57 ` [RFC PATCH 04/16] mm/damon/core: ask apply_probe() to return max probe hits weighted sum SJ Park
2026-07-05 20:57 ` [RFC PATCH 05/16] mm/damon/core: implement damon_probe_hits_wsum() SJ Park
2026-07-05 21:13 ` sashiko-bot
2026-07-05 21:30 ` SJ Park
2026-07-05 20:57 ` [RFC PATCH 06/16] mm/damon/paddr: respect return_max_wsum SJ Park
2026-07-05 20:57 ` [RFC PATCH 07/16] mm/damon/core: extend merge function to work with probe hits SJ Park
2026-07-05 21:11 ` sashiko-bot [this message]
2026-07-05 21:38 ` SJ Park
2026-07-05 20:57 ` [RFC PATCH 08/16] mm/damon/core: disable access monitoring when probe weights are set SJ Park
2026-07-05 21:19 ` sashiko-bot
2026-07-05 20:57 ` [RFC PATCH 09/16] mm/damon/core: set samples in apply_probes() if " SJ Park
2026-07-05 20:57 ` [RFC PATCH 10/16] mm/damon/core: s/max_nr_accesses/max_merge_score/ in kdamond_fn() SJ Park
2026-07-05 20:57 ` [RFC PATCH 11/16] mm/damon/core: get merge threshold from probe hits when weights are set SJ Park
2026-07-05 21:12 ` sashiko-bot
2026-07-05 21:41 ` SJ Park
2026-07-05 20:57 ` [RFC PATCH 12/16] mm/damon/core: implement damon_has_probe_weight() SJ Park
2026-07-05 21:15 ` sashiko-bot
2026-07-05 21:45 ` SJ Park
2026-07-05 20:57 ` [RFC PATCH 13/16] mm/damon/sysfs: implement probe/weight file SJ Park
2026-07-05 20:57 ` [RFC PATCH 14/16] Docs/mm/damon/design: document attrs-only monitoring SJ Park
2026-07-05 21:05 ` sashiko-bot
2026-07-05 21:46 ` SJ Park
2026-07-05 20:57 ` [RFC PATCH 15/16] Docs/admin-guide/mm/damon/usage: document weight sysfs file SJ Park
2026-07-05 21:07 ` sashiko-bot
2026-07-05 21:48 ` SJ Park
2026-07-05 20:57 ` [RFC PATCH 16/16] Docs/ABI/damon: document probe weight file SJ Park
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260705211101.F2F061F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=damon@lists.linux.dev \
--cc=sashiko-reviews@lists.linux.dev \
--cc=sj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.