* [PATCH 0/2] mm/damon: avoid division by zero from damos_quota_score()
@ 2026-08-03 13:40 SJ Park
2026-08-03 13:40 ` [PATCH 1/2] samples/damon/mtier: error out for zero quota goal target values SJ Park
2026-08-03 13:40 ` [PATCH 2/2] mm/damon/lru_sort: error out for >10000 active_mem_bp SJ Park
0 siblings, 2 replies; 7+ messages in thread
From: SJ Park @ 2026-08-03 13:40 UTC (permalink / raw)
To: Andrew Morton
Cc: SJ Park, stable, Yunjeong Mun, damon, linux-kernel, linux-mm
DAMON_SAMPLE_MTIER and DAMON_LRU_SORT allow the user to trigger division
by zero in damos_quota_score(). Avoid it by adding parameters
validation checks.
Changes from RFC v2
- RFC v2: https://lore.kernel.org/20260802162050.89477-1-sj@kernel.org
- Drop RFC tag.
Changes from RFC
- RFC: https://lore.kernel.org/20260801211315.2456-1-sj@kernel.org
- Add a fix for DAMON_LRU_SORT.
SJ Park (2):
samples/damon/mtier: error out for zero quota goal target values
mm/damon/lru_sort: error out for >10000 active_mem_bp
mm/damon/lru_sort.c | 2 ++
samples/damon/mtier.c | 3 +++
2 files changed, 5 insertions(+)
base-commit: 3bf69d5b51b688b8f923a13b7f12eb9b1c6a284f
--
2.47.3
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 1/2] samples/damon/mtier: error out for zero quota goal target values
2026-08-03 13:40 [PATCH 0/2] mm/damon: avoid division by zero from damos_quota_score() SJ Park
@ 2026-08-03 13:40 ` SJ Park
2026-08-03 14:06 ` sashiko-bot
2026-08-03 13:40 ` [PATCH 2/2] mm/damon/lru_sort: error out for >10000 active_mem_bp SJ Park
1 sibling, 1 reply; 7+ messages in thread
From: SJ Park @ 2026-08-03 13:40 UTC (permalink / raw)
To: Andrew Morton
Cc: SJ Park, stable, Yunjeong Mun, damon, linux-kernel, linux-mm
damos_quota_score() can trigger division by zero if the target_value is
zero. DAMON_SAMPLE_MTIER lets users set the target_value via
node0_mem_{used,free}_bp parameters. It doesn't guard zero value case,
though. As a result, users can trigger division by zero. Fix the issue
by returning an error when the user tries to start DAMON with zero
node0_mem_{used,free}_bp parameter values.
DAMON_SAMPLE_MTIER is just a sample module, but the consequence is quite
bad. Also the zero node0_mem_free_bp parameter might look like a
reasonable setup to some users. Hence, the issue might really happen in
the real world.
One reliable way to reproduce the issue is like below:
# cd /sys/module/damon_sample_mtier/parameters
# echo 4096 > node0_start_addr
# echo 8192 > node0_end_addr
# echo 8192 > node1_start_addr
# echo 81920 > node1_end_addr
# echo 0 > node0_mem_free_bp
# echo Y > enabled
# dmesg -w
[...]
[18792.235916] Oops: divide error: 0000 [#1] SMP NOPTI
[...]
[18792.242787] RIP: 0010:damos_quota_score+0x6f/0x480
[...]
This issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/20260801202657.117135-1-sj@kernel.org
Fixes: c5e67d40a102 ("samples/damon/mtier: add parameters for node0 memory usage")
Cc: <stable@vger.kernel.org> # 6.17.x
Signed-off-by: SJ Park <sj@kernel.org>
---
samples/damon/mtier.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/samples/damon/mtier.c b/samples/damon/mtier.c
index ac9c24b92ead8..d1123ebbfab90 100644
--- a/samples/damon/mtier.c
+++ b/samples/damon/mtier.c
@@ -156,6 +156,9 @@ static struct damon_ctx *damon_sample_mtier_build_ctx(bool promote)
if (!scheme)
goto free_out;
damon_set_schemes(ctx, &scheme, 1);
+ /* zero target value causes division by zero in damos_quota_store() */
+ if (!node0_mem_used_bp || !node0_mem_free_bp)
+ goto free_out;
quota_goal = damos_new_quota_goal(
promote ? DAMOS_QUOTA_NODE_MEM_USED_BP :
DAMOS_QUOTA_NODE_MEM_FREE_BP,
--
2.47.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 2/2] mm/damon/lru_sort: error out for >10000 active_mem_bp
2026-08-03 13:40 [PATCH 0/2] mm/damon: avoid division by zero from damos_quota_score() SJ Park
2026-08-03 13:40 ` [PATCH 1/2] samples/damon/mtier: error out for zero quota goal target values SJ Park
@ 2026-08-03 13:40 ` SJ Park
2026-08-03 14:57 ` David Laight
1 sibling, 1 reply; 7+ messages in thread
From: SJ Park @ 2026-08-03 13:40 UTC (permalink / raw)
To: Andrew Morton; +Cc: SJ Park, stable, damon, linux-kernel, linux-mm
damos_quota_score() can trigger division by zero if the target value is
zero. DAMON_LRU_SORT lets users set the target value for the hot memory
scheme via active_mem_bp parameter. It avoids setting it as the target
value if the parameter value is zero. However, it also sets the cold
memory scheme with a target value that is calculated as '10000 -
active_mem_bp + 2'. Hence, if a user sets active_mem_bp 10002, the cold
memory scheme's quota goal target value can be zero. As a result,
division by zero can be triggered. Fix by returning an error when the
user tries to start DAMON with >10000 active_mem_bp parameter value.
It makes no sense to set active_mem_bp with 10002. It also requires
module parameters write permission to reproduce the issue. That said,
the consequence is quite bad.
One reliable way to reproduce the issue is like below:
# cd /sys/module/damon_lru_sort/parameters
# echo 1000 > wmarks_high
# echo 995 > wmarks_mid
# echo 0 > wmarks_low
# echo 10002 > active_mem_bp
# echo Y > enabled
# dmesg -w
[...]
[ 597.421247] Oops: divide error: 0000 [#1] SMP NOPTI
[ 597.428848] RIP: 0010:damos_quota_score+0x6f/0x480
This issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/20260801213028.5127-1-sj@kernel.org
Fixes: 40d98d31cd70 ("mm/damon/lru_sort: support active:inactive memory ratio based auto-tuning")
Cc: <stable@vger.kernel.org> # 7.0.x
Signed-off-by: SJ Park <sj@kernel.org>
---
mm/damon/lru_sort.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
index 7e077084cb03a..3920d5042f109 100644
--- a/mm/damon/lru_sort.c
+++ b/mm/damon/lru_sort.c
@@ -233,6 +233,8 @@ static int damon_lru_sort_add_quota_goals(struct damos *hot_scheme,
if (!active_mem_bp)
return 0;
+ if (10000 < active_mem_bp)
+ return -EINVAL;
goal = damos_new_quota_goal(DAMOS_QUOTA_ACTIVE_MEM_BP, active_mem_bp);
if (!goal)
return -ENOMEM;
--
2.47.3
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] samples/damon/mtier: error out for zero quota goal target values
2026-08-03 13:40 ` [PATCH 1/2] samples/damon/mtier: error out for zero quota goal target values SJ Park
@ 2026-08-03 14:06 ` sashiko-bot
2026-08-03 14:18 ` SJ Park
0 siblings, 1 reply; 7+ messages in thread
From: sashiko-bot @ 2026-08-03 14:06 UTC (permalink / raw)
To: SJ Park; +Cc: damon
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] The safety check for zero values evaluates global module parameters without `READ_ONCE()`, introducing a TOCTOU race window that bypasses the patch's defense.
- [Low] The newly added comment references a non-existent function `damos_quota_store()` instead of `damos_quota_score()`.
Pre-existing issues:
- [High] The core API `damos_new_quota_goal()` fails to validate `target_value != 0`, forcing ad-hoc checks in caller modules and leaving the subsystem vulnerable to division by zero.
- [High] The DAMON LRU sort module computes a quota goal target value from an unvalidated module parameter, allowing users to trigger a division by zero crash.
--
--- Patch [1]: [PATCH 1/2] samples/damon/mtier: error out for zero quota goal target values ---
commit 8e87b5068bfcd9e35bdbd23dadaa97f649431adb
Author: SJ Park <sj@kernel.org>
samples/damon/mtier: error out for zero quota goal target values
This patch prevents a division by zero in damos_quota_score() by returning
an error when a user configures DAMON with zero target values for the
node0_mem_used_bp or node0_mem_free_bp module parameters.
Link: https://lore.kernel.org/20260801202657.117135-1-sj@kernel.org
> diff --git a/samples/damon/mtier.c b/samples/damon/mtier.c
> index ac9c24b92ead8..d1123ebbfab90 100644
> --- a/samples/damon/mtier.c
> +++ b/samples/damon/mtier.c
> @@ -156,6 +156,9 @@ static struct damon_ctx *damon_sample_mtier_build_ctx(bool promote)
> if (!scheme)
> goto free_out;
> damon_set_schemes(ctx, &scheme, 1);
> + /* zero target value causes division by zero in damos_quota_store() */
[Severity: Low]
This isn't a bug, but there is a typo in the comment. Should
damos_quota_store() be damos_quota_score()?
> + if (!node0_mem_used_bp || !node0_mem_free_bp)
> + goto free_out;
> quota_goal = damos_new_quota_goal(
> promote ? DAMOS_QUOTA_NODE_MEM_USED_BP :
> DAMOS_QUOTA_NODE_MEM_FREE_BP,
> promote ? node0_mem_used_bp : node0_mem_free_bp);
[Severity: High]
Can a concurrent sysfs write bypass this safety check?
The module parameters node0_mem_used_bp and node0_mem_free_bp are read
multiple times without READ_ONCE().
A concurrent thread could set a non-zero value to pass the check, and then
overwrite it with zero before damos_new_quota_goal() reads the parameter
again.
Would this re-introduce the division by zero crash?
This same double-read pattern appears to be present in other DAMON modules:
mm/damon/lru_sort.c:damon_lru_sort_add_quota_goals() {
if (!active_mem_bp)
return 0;
goal = damos_new_quota_goal(DAMOS_QUOTA_ACTIVE_MEM_BP, active_mem_bp);
...
}
mm/damon/reclaim.c:damon_reclaim_apply_parameters() {
if (quota_mem_pressure_us) {
goal = damos_new_quota_goal(DAMOS_QUOTA_SOME_MEM_PSI_US,
quota_mem_pressure_us);
...
}
Should these parameters be cached in local variables or read with READ_ONCE()
to prevent a Time-of-Check to Time-of-Use race?
[Severity: High]
This is a pre-existing issue, but does the core API damos_new_quota_goal()
need a check for a zero target_value?
Currently, callers are responsible for validating the target value to avoid
a division by zero in damos_quota_score(). If damos_new_quota_goal()
validated this and returned NULL when target_value is 0, it would protect
the entire DAMON subsystem systematically without relying on ad-hoc checks
in caller modules:
mm/damon/core.c:damos_new_quota_goal() {
struct damos_quota_goal *goal;
goal = kmalloc_obj(*goal);
if (!goal)
return NULL;
goal->metric = metric;
goal->target_value = target_value;
...
}
[Severity: High]
This is a pre-existing issue, but can the LRU sort module trigger a division
by zero despite parameter validation?
In damon_lru_sort_add_quota_goals(), the cold scheme's quota goal is
computed dynamically:
mm/damon/lru_sort.c:damon_lru_sort_add_quota_goals() {
...
goal = damos_new_quota_goal(DAMOS_QUOTA_INACTIVE_MEM_BP,
10000 - active_mem_bp + 2);
...
}
If a user configures the active_mem_bp module parameter to exactly 10002
via sysfs, the resulting target_value evaluates to 0.
Since this value is passed directly to damos_new_quota_goal(), wouldn't this
crash the kernel in damos_quota_score()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260803134034.15217-1-sj@kernel.org?part=1
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] samples/damon/mtier: error out for zero quota goal target values
2026-08-03 14:06 ` sashiko-bot
@ 2026-08-03 14:18 ` SJ Park
0 siblings, 0 replies; 7+ messages in thread
From: SJ Park @ 2026-08-03 14:18 UTC (permalink / raw)
To: sashiko-bot; +Cc: SJ Park, damon
On Mon, 03 Aug 2026 14:06:52 +0000 sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
>
> New issues:
> - [High] The safety check for zero values evaluates global module parameters without `READ_ONCE()`, introducing a TOCTOU race window that bypasses the patch's defense.
> - [Low] The newly added comment references a non-existent function `damos_quota_store()` instead of `damos_quota_score()`.
>
> Pre-existing issues:
> - [High] The core API `damos_new_quota_goal()` fails to validate `target_value != 0`, forcing ad-hoc checks in caller modules and leaving the subsystem vulnerable to division by zero.
> - [High] The DAMON LRU sort module computes a quota goal target value from an unvalidated module parameter, allowing users to trigger a division by zero crash.
> --
>
> --- Patch [1]: [PATCH 1/2] samples/damon/mtier: error out for zero quota goal target values ---
> commit 8e87b5068bfcd9e35bdbd23dadaa97f649431adb
> Author: SJ Park <sj@kernel.org>
>
> samples/damon/mtier: error out for zero quota goal target values
>
> This patch prevents a division by zero in damos_quota_score() by returning
> an error when a user configures DAMON with zero target values for the
> node0_mem_used_bp or node0_mem_free_bp module parameters.
>
> Link: https://lore.kernel.org/20260801202657.117135-1-sj@kernel.org
>
> > diff --git a/samples/damon/mtier.c b/samples/damon/mtier.c
> > index ac9c24b92ead8..d1123ebbfab90 100644
> > --- a/samples/damon/mtier.c
> > +++ b/samples/damon/mtier.c
> > @@ -156,6 +156,9 @@ static struct damon_ctx *damon_sample_mtier_build_ctx(bool promote)
> > if (!scheme)
> > goto free_out;
> > damon_set_schemes(ctx, &scheme, 1);
> > + /* zero target value causes division by zero in damos_quota_store() */
>
> [Severity: Low]
> This isn't a bug, but there is a typo in the comment. Should
> damos_quota_store() be damos_quota_score()?
>
> > + if (!node0_mem_used_bp || !node0_mem_free_bp)
> > + goto free_out;
> > quota_goal = damos_new_quota_goal(
> > promote ? DAMOS_QUOTA_NODE_MEM_USED_BP :
> > DAMOS_QUOTA_NODE_MEM_FREE_BP,
> > promote ? node0_mem_used_bp : node0_mem_free_bp);
>
> [Severity: High]
> Can a concurrent sysfs write bypass this safety check?
>
> The module parameters node0_mem_used_bp and node0_mem_free_bp are read
> multiple times without READ_ONCE().
>
> A concurrent thread could set a non-zero value to pass the check, and then
> overwrite it with zero before damos_new_quota_goal() reads the parameter
> again.
>
> Would this re-introduce the division by zero crash?
>
> This same double-read pattern appears to be present in other DAMON modules:
>
> mm/damon/lru_sort.c:damon_lru_sort_add_quota_goals() {
> if (!active_mem_bp)
> return 0;
> goal = damos_new_quota_goal(DAMOS_QUOTA_ACTIVE_MEM_BP, active_mem_bp);
> ...
> }
>
> mm/damon/reclaim.c:damon_reclaim_apply_parameters() {
> if (quota_mem_pressure_us) {
> goal = damos_new_quota_goal(DAMOS_QUOTA_SOME_MEM_PSI_US,
> quota_mem_pressure_us);
> ...
> }
>
> Should these parameters be cached in local variables or read with READ_ONCE()
> to prevent a Time-of-Check to Time-of-Use race?
No, such race is avoided by param_lock.
>
>
> [Severity: High]
> This is a pre-existing issue, but does the core API damos_new_quota_goal()
> need a check for a zero target_value?
>
> Currently, callers are responsible for validating the target value to avoid
> a division by zero in damos_quota_score(). If damos_new_quota_goal()
> validated this and returned NULL when target_value is 0, it would protect
> the entire DAMON subsystem systematically without relying on ad-hoc checks
> in caller modules:
>
> mm/damon/core.c:damos_new_quota_goal() {
> struct damos_quota_goal *goal;
>
> goal = kmalloc_obj(*goal);
> if (!goal)
> return NULL;
> goal->metric = metric;
> goal->target_value = target_value;
> ...
> }
I'm planning to make a long term fix in the core layer later.
>
>
> [Severity: High]
> This is a pre-existing issue, but can the LRU sort module trigger a division
> by zero despite parameter validation?
>
> In damon_lru_sort_add_quota_goals(), the cold scheme's quota goal is
> computed dynamically:
>
> mm/damon/lru_sort.c:damon_lru_sort_add_quota_goals() {
> ...
> goal = damos_new_quota_goal(DAMOS_QUOTA_INACTIVE_MEM_BP,
> 10000 - active_mem_bp + 2);
> ...
> }
>
> If a user configures the active_mem_bp module parameter to exactly 10002
> via sysfs, the resulting target_value evaluates to 0.
>
> Since this value is passed directly to damos_new_quota_goal(), wouldn't this
> crash the kernel in damos_quota_score()?
The next patch of this series fixes the bug.
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260803134034.15217-1-sj@kernel.org?part=1
Thanks,
SJ
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] mm/damon/lru_sort: error out for >10000 active_mem_bp
2026-08-03 13:40 ` [PATCH 2/2] mm/damon/lru_sort: error out for >10000 active_mem_bp SJ Park
@ 2026-08-03 14:57 ` David Laight
2026-08-04 0:16 ` SJ Park
0 siblings, 1 reply; 7+ messages in thread
From: David Laight @ 2026-08-03 14:57 UTC (permalink / raw)
To: SJ Park; +Cc: Andrew Morton, stable, damon, linux-kernel, linux-mm
On Mon, 3 Aug 2026 06:40:33 -0700
SJ Park <sj@kernel.org> wrote:
> damos_quota_score() can trigger division by zero if the target value is
> zero. DAMON_LRU_SORT lets users set the target value for the hot memory
> scheme via active_mem_bp parameter. It avoids setting it as the target
> value if the parameter value is zero. However, it also sets the cold
> memory scheme with a target value that is calculated as '10000 -
> active_mem_bp + 2'. Hence, if a user sets active_mem_bp 10002, the cold
> memory scheme's quota goal target value can be zero. As a result,
> division by zero can be triggered. Fix by returning an error when the
> user tries to start DAMON with >10000 active_mem_bp parameter value.
>
> It makes no sense to set active_mem_bp with 10002. It also requires
> module parameters write permission to reproduce the issue. That said,
> the consequence is quite bad.
>
> One reliable way to reproduce the issue is like below:
>
> # cd /sys/module/damon_lru_sort/parameters
> # echo 1000 > wmarks_high
> # echo 995 > wmarks_mid
> # echo 0 > wmarks_low
> # echo 10002 > active_mem_bp
> # echo Y > enabled
> # dmesg -w
> [...]
> [ 597.421247] Oops: divide error: 0000 [#1] SMP NOPTI
> [ 597.428848] RIP: 0010:damos_quota_score+0x6f/0x480
>
> This issue was discovered [1] by Sashiko.
>
> [1] https://lore.kernel.org/20260801213028.5127-1-sj@kernel.org
>
> Fixes: 40d98d31cd70 ("mm/damon/lru_sort: support active:inactive memory ratio based auto-tuning")
> Cc: <stable@vger.kernel.org> # 7.0.x
> Signed-off-by: SJ Park <sj@kernel.org>
> ---
> mm/damon/lru_sort.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
> index 7e077084cb03a..3920d5042f109 100644
> --- a/mm/damon/lru_sort.c
> +++ b/mm/damon/lru_sort.c
> @@ -233,6 +233,8 @@ static int damon_lru_sort_add_quota_goals(struct damos *hot_scheme,
>
> if (!active_mem_bp)
> return 0;
> + if (10000 < active_mem_bp)
That is backwards...
> + return -EINVAL;
> goal = damos_new_quota_goal(DAMOS_QUOTA_ACTIVE_MEM_BP, active_mem_bp);
> if (!goal)
> return -ENOMEM;
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] mm/damon/lru_sort: error out for >10000 active_mem_bp
2026-08-03 14:57 ` David Laight
@ 2026-08-04 0:16 ` SJ Park
0 siblings, 0 replies; 7+ messages in thread
From: SJ Park @ 2026-08-04 0:16 UTC (permalink / raw)
To: David Laight
Cc: SJ Park, Andrew Morton, stable, damon, linux-kernel, linux-mm
On Mon, 3 Aug 2026 15:57:15 +0100 David Laight <david.laight.linux@gmail.com> wrote:
> On Mon, 3 Aug 2026 06:40:33 -0700
> SJ Park <sj@kernel.org> wrote:
[...]
> > --- a/mm/damon/lru_sort.c
> > +++ b/mm/damon/lru_sort.c
> > @@ -233,6 +233,8 @@ static int damon_lru_sort_add_quota_goals(struct damos *hot_scheme,
> >
> > if (!active_mem_bp)
> > return 0;
> > + if (10000 < active_mem_bp)
>
> That is backwards...
I tend to prefer using only '<' or '<=' because it makes smaller thing comes
left. But maybe I was overusing that here. I think 'active_mem_bp > 10000'
should also reads well. I will think more carefully for this, from the next
time. Andrew already picked this up and he should be busy for next
merge window preparation. Hence I'll not revision this for the minor change,
if you don't mind.
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-08-04 0:16 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-03 13:40 [PATCH 0/2] mm/damon: avoid division by zero from damos_quota_score() SJ Park
2026-08-03 13:40 ` [PATCH 1/2] samples/damon/mtier: error out for zero quota goal target values SJ Park
2026-08-03 14:06 ` sashiko-bot
2026-08-03 14:18 ` SJ Park
2026-08-03 13:40 ` [PATCH 2/2] mm/damon/lru_sort: error out for >10000 active_mem_bp SJ Park
2026-08-03 14:57 ` David Laight
2026-08-04 0:16 ` SJ Park
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).