* [PATCH 6.18.y] mm/damon/reclaim: detect and use fresh enabled and kdamond_pid values [not found] <2026051254-walrus-thrift-66bc@gregkh> @ 2026-05-13 4:39 ` SeongJae Park 2026-05-14 2:02 ` sashiko-bot 0 siblings, 1 reply; 3+ messages in thread From: SeongJae Park @ 2026-05-13 4:39 UTC (permalink / raw) To: stable; +Cc: SeongJae Park, damon, Liew Rui Yan, Andrew Morton Patch series "mm/damon/modules: detect and use fresh status", v3. DAMON modules including DAMON_RECLAIM, DAMON_LRU_SORT and DAMON_STAT commonly expose the kdamond running status via their parameters. Under certain scenarios including wrong user inputs and memory allocation failures, those parameter values can be stale. It can confuse users. For DAMON_RECLAIM and DAMON_LRU_SORT, it even makes the kdamond unable to be restarted before the system reboot. The problem comes from the fact that there are multiple events for the status changes and it is difficult to follow up all the scenarios. Fix the issue by detecting and using the status on demand, instead of using a cached status that is difficult to be updated. Patches 1-3 fix the bugs in DAMON_RECLAIM, DAMON_LRU_SORT and DAMON_STAT in the order. This patch (of 3): DAMON_RECLAIM updates 'enabled' and 'kdamond_pid' parameter values, which represents the running status of its kdamond, when the user explicitly requests start/stop of the kdamond. The kdamond can, however, be stopped in events other than the explicit user request in the following three events. 1. ctx->regions_score_histogram allocation failure at beginning of the execution, 2. damon_commit_ctx() failure due to invalid user input, and 3. damon_commit_ctx() failure due to its internal allocation failures. Hence, if the kdamond is stopped by the above three events, the values of the status parameters can be stale. Users could show the stale values and be confused. This is already bad, but the real consequence is worse. DAMON_RECLAIM avoids unnecessary damon_start() and damon_stop() calls based on the 'enabled' parameter value. And the update of 'enabled' parameter value depends on the damon_start() and damon_stop() call results. Hence, once the kdamond has stopped by the unintentional events, the user cannot restart the kdamond before the system reboot. For example, the issue can be reproduced via below steps. # cd /sys/module/damon_reclaim/parameters # # # start DAMON_RECLAIM # echo Y > enabled # ps -ef | grep kdamond root 806 2 0 17:53 ? 00:00:00 [kdamond.0] root 808 803 0 17:53 pts/4 00:00:00 grep kdamond # # # commit wrong input to stop kdamond withou explicit stop request # echo 3 > addr_unit # echo Y > commit_inputs bash: echo: write error: Invalid argument # # # confirm kdamond is stopped # ps -ef | grep kdamond root 811 803 0 17:53 pts/4 00:00:00 grep kdamond # # # users casn now show stable status # cat enabled Y # cat kdamond_pid 806 # # # even after fixing the wrong parameter, # # kdamond cannot be restarted. # echo 1 > addr_unit # echo Y > enabled # ps -ef | grep kdamond root 815 803 0 17:54 pts/4 00:00:00 grep kdamond The problem will only rarely happen in real and common setups for the following reasons. The allocation failures are unlikely in such setups since those allocations are arguably too small to fail. Also sane users on real production environments may not commit wrong input parameters. But once it happens, the consequence is quite bad. And the bug is a bug. The issue stems from the fact that there are multiple events that can change the status, and following all the events is challenging. Dynamically detect and use the fresh status for the parameters when those are requested. Link: https://lore.kernel.org/20260419161003.79176-1-sj@kernel.org Link: https://lore.kernel.org/20260419161003.79176-2-sj@kernel.org Fixes: e035c280f6df ("mm/damon/reclaim: support online inputs update") Co-developed-by: Liew Rui Yan <aethernet65535@gmail.com> Signed-off-by: Liew Rui Yan <aethernet65535@gmail.com> Signed-off-by: SeongJae Park <sj@kernel.org> Cc: <stable@vger.kernel.org> # 5.19.x Signed-off-by: Andrew Morton <akpm@linux-foundation.org> (cherry picked from commit 64a140afa5ed1c6f5ba6d451512cbdbbab1ba339) Signed-off-by: SeongJae Park <sj@kernel.org> --- This depends on another backported patch [1]. Please apply this after that. [1] https://lore.kernel.org/20260513034229.131258-1-sj@kernel.org mm/damon/reclaim.c | 83 ++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 28 deletions(-) diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c index 7ba3d0f9a19ac..9446e7a1b476f 100644 --- a/mm/damon/reclaim.c +++ b/mm/damon/reclaim.c @@ -144,15 +144,6 @@ static unsigned long addr_unit __read_mostly = 1; static bool skip_anon __read_mostly; module_param(skip_anon, bool, 0600); -/* - * PID of the DAMON thread - * - * If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread. - * Else, -1. - */ -static int kdamond_pid __read_mostly = -1; -module_param(kdamond_pid, int, 0400); - static struct damos_stat damon_reclaim_stat; DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_reclaim_stat, reclaim_tried_regions, reclaimed_regions, quota_exceeds); @@ -292,12 +283,8 @@ static int damon_reclaim_turn(bool on) { int err; - if (!on) { - err = damon_stop(&ctx, 1); - if (!err) - kdamond_pid = -1; - return err; - } + if (!on) + return damon_stop(&ctx, 1); err = damon_reclaim_apply_parameters(); if (err) @@ -306,7 +293,6 @@ static int damon_reclaim_turn(bool on) err = damon_start(&ctx, 1, true); if (err) return err; - kdamond_pid = ctx->kdamond->pid; return damon_call(ctx, &call_control); } @@ -334,42 +320,83 @@ module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600); MODULE_PARM_DESC(addr_unit, "Scale factor for DAMON_RECLAIM to ops address conversion (default: 1)"); +static bool damon_reclaim_enabled(void) +{ + if (!ctx) + return false; + return damon_is_running(ctx); +} + static int damon_reclaim_enabled_store(const char *val, const struct kernel_param *kp) { - bool is_enabled = enabled; - bool enable; int err; - err = kstrtobool(val, &enable); + err = kstrtobool(val, &enabled); if (err) return err; - if (is_enabled == enable) + if (damon_reclaim_enabled() == enabled) return 0; /* Called before init function. The function will handle this. */ if (!damon_initialized()) - goto set_param_out; + return 0; - err = damon_reclaim_turn(enable); - if (err) - return err; + return damon_reclaim_turn(enabled); +} -set_param_out: - enabled = enable; - return err; +static int damon_reclaim_enabled_load(char *buffer, + const struct kernel_param *kp) +{ + return sprintf(buffer, "%c\n", damon_reclaim_enabled() ? 'Y' : 'N'); } static const struct kernel_param_ops enabled_param_ops = { .set = damon_reclaim_enabled_store, - .get = param_get_bool, + .get = damon_reclaim_enabled_load, }; module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); MODULE_PARM_DESC(enabled, "Enable or disable DAMON_RECLAIM (default: disabled)"); +static int damon_reclaim_kdamond_pid_store(const char *val, + const struct kernel_param *kp) +{ + /* + * kdamond_pid is read-only, but kernel command line could write it. + * Do nothing here. + */ + return 0; +} + +static int damon_reclaim_kdamond_pid_load(char *buffer, + const struct kernel_param *kp) +{ + int kdamond_pid = -1; + + if (ctx) { + kdamond_pid = damon_kdamond_pid(ctx); + if (kdamond_pid < 0) + kdamond_pid = -1; + } + return sprintf(buffer, "%d\n", kdamond_pid); +} + +static const struct kernel_param_ops kdamond_pid_param_ops = { + .set = damon_reclaim_kdamond_pid_store, + .get = damon_reclaim_kdamond_pid_load, +}; + +/* + * PID of the DAMON thread + * + * If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread. + * Else, -1. + */ +module_param_cb(kdamond_pid, &kdamond_pid_param_ops, NULL, 0400); + static int __init damon_reclaim_init(void) { int err; -- 2.47.3 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 6.18.y] mm/damon/reclaim: detect and use fresh enabled and kdamond_pid values 2026-05-13 4:39 ` [PATCH 6.18.y] mm/damon/reclaim: detect and use fresh enabled and kdamond_pid values SeongJae Park @ 2026-05-14 2:02 ` sashiko-bot 2026-05-14 5:35 ` SeongJae Park 0 siblings, 1 reply; 3+ messages in thread From: sashiko-bot @ 2026-05-14 2:02 UTC (permalink / raw) To: SeongJae Park; +Cc: damon Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] Writing to the `enabled` sysfs parameter triggers a NULL pointer dereference if the module's initialization failed. - [Low] The commit introduces a call to an undefined function `damon_kdamond_pid()`, causing a build failure. -- commit 45d783d4b3fd23532d7c6b975b70fda3e5324f1b Author: SeongJae Park <sj@kernel.org> mm/damon/reclaim: detect and use fresh enabled and kdamond_pid values This commit modifies the DAMON reclaim module to dynamically detect and use the fresh running status of kdamond when parameters are requested. This prevents stale cached statuses from being shown to users when kdamond stops unexpectedly. Link: https://lore.kernel.org/20260419161003.79176-1-sj@kernel.org Link: https://lore.kernel.org/20260419161003.79176-2-sj@kernel.org > diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c > index 7ba3d0f9a19ac..9446e7a1b476f 100644 > --- a/mm/damon/reclaim.c > +++ b/mm/damon/reclaim.c [ ... ] > @@ -334,42 +320,83 @@ module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600); > MODULE_PARM_DESC(addr_unit, > "Scale factor for DAMON_RECLAIM to ops address conversion (default: 1)"); > > +static bool damon_reclaim_enabled(void) > +{ > + if (!ctx) > + return false; > + return damon_is_running(ctx); > +} > + > static int damon_reclaim_enabled_store(const char *val, > const struct kernel_param *kp) > { > - bool is_enabled = enabled; > - bool enable; > int err; > > - err = kstrtobool(val, &enable); > + err = kstrtobool(val, &enabled); > if (err) > return err; > > - if (is_enabled == enable) > + if (damon_reclaim_enabled() == enabled) > return 0; > > /* Called before init function. The function will handle this. */ > if (!damon_initialized()) > - goto set_param_out; > + return 0; > > - err = damon_reclaim_turn(enable); > - if (err) > - return err; > + return damon_reclaim_turn(enabled); > +} If module initialization fails during boot, for example due to an allocation failure in damon_modules_new_paddr_ctx_target(), the global ctx pointer will remain NULL. Because damon_reclaim is built-in, its sysfs parameters are still exposed. If a user subsequently writes to the enabled parameter, damon_reclaim_enabled_store() will see that damon_initialized() is true because the global cache is initialized, and it will call damon_reclaim_turn(). This unconditionally passes the NULL ctx pointer to either damon_stop() or damon_reclaim_apply_parameters(), which eventually calls damon_commit_ctx(). Could this cause a NULL pointer dereference when accessing the uninitialized ctx pointer? [ ... ] > +static int damon_reclaim_kdamond_pid_load(char *buffer, > + const struct kernel_param *kp) > +{ > + int kdamond_pid = -1; > + > + if (ctx) { > + kdamond_pid = damon_kdamond_pid(ctx); Is the function damon_kdamond_pid() defined anywhere in the tree? It appears this function is called here but might be missing, which would cause an implicit declaration and linker error. Could a prerequisite patch be missing from this cherry-pick? > + if (kdamond_pid < 0) > + kdamond_pid = -1; > + } > + return sprintf(buffer, "%d\n", kdamond_pid); > +} -- Sashiko AI review · https://sashiko.dev/#/patchset/20260513043902.183499-1-sj@kernel.org?part=1 ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH 6.18.y] mm/damon/reclaim: detect and use fresh enabled and kdamond_pid values 2026-05-14 2:02 ` sashiko-bot @ 2026-05-14 5:35 ` SeongJae Park 0 siblings, 0 replies; 3+ messages in thread From: SeongJae Park @ 2026-05-14 5:35 UTC (permalink / raw) To: sashiko-bot; +Cc: SeongJae Park, damon On Thu, 14 May 2026 02:02:41 +0000 sashiko-bot@kernel.org wrote: > Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: > - [High] Writing to the `enabled` sysfs parameter triggers a NULL pointer dereference if the module's initialization failed. > - [Low] The commit introduces a call to an undefined function `damon_kdamond_pid()`, causing a build failure. > -- > > commit 45d783d4b3fd23532d7c6b975b70fda3e5324f1b > Author: SeongJae Park <sj@kernel.org> > mm/damon/reclaim: detect and use fresh enabled and kdamond_pid values > > This commit modifies the DAMON reclaim module to dynamically detect and use > the fresh running status of kdamond when parameters are requested. This > prevents stale cached statuses from being shown to users when kdamond stops > unexpectedly. > > Link: https://lore.kernel.org/20260419161003.79176-1-sj@kernel.org > Link: https://lore.kernel.org/20260419161003.79176-2-sj@kernel.org > > > diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c > > index 7ba3d0f9a19ac..9446e7a1b476f 100644 > > --- a/mm/damon/reclaim.c > > +++ b/mm/damon/reclaim.c > > [ ... ] > > > @@ -334,42 +320,83 @@ module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600); > > MODULE_PARM_DESC(addr_unit, > > "Scale factor for DAMON_RECLAIM to ops address conversion (default: 1)"); > > > > +static bool damon_reclaim_enabled(void) > > +{ > > + if (!ctx) > > + return false; > > + return damon_is_running(ctx); > > +} > > + > > static int damon_reclaim_enabled_store(const char *val, > > const struct kernel_param *kp) > > { > > - bool is_enabled = enabled; > > - bool enable; > > int err; > > > > - err = kstrtobool(val, &enable); > > + err = kstrtobool(val, &enabled); > > if (err) > > return err; > > > > - if (is_enabled == enable) > > + if (damon_reclaim_enabled() == enabled) > > return 0; > > > > /* Called before init function. The function will handle this. */ > > if (!damon_initialized()) > > - goto set_param_out; > > + return 0; > > > > - err = damon_reclaim_turn(enable); > > - if (err) > > - return err; > > + return damon_reclaim_turn(enabled); > > +} > > If module initialization fails during boot, for example due to an allocation > failure in damon_modules_new_paddr_ctx_target(), the global ctx pointer will > remain NULL. Because damon_reclaim is built-in, its sysfs parameters are > still exposed. > > If a user subsequently writes to the enabled parameter, > damon_reclaim_enabled_store() will see that damon_initialized() is true > because the global cache is initialized, and it will call > damon_reclaim_turn(). > > This unconditionally passes the NULL ctx pointer to either damon_stop() or > damon_reclaim_apply_parameters(), which eventually calls damon_commit_ctx(). > > Could this cause a NULL pointer dereference when accessing the uninitialized > ctx pointer? Sashiko reported [1] same thing before, and I'm working on it. > > [ ... ] > > > +static int damon_reclaim_kdamond_pid_load(char *buffer, > > + const struct kernel_param *kp) > > +{ > > + int kdamond_pid = -1; > > + > > + if (ctx) { > > + kdamond_pid = damon_kdamond_pid(ctx); > > Is the function damon_kdamond_pid() defined anywhere in the tree? > > It appears this function is called here but might be missing, which would > cause an implicit declaration and linker error. Could a prerequisite patch be > missing from this cherry-pick? I informed this issue and where the dependent patch can be found, on the commentary area of the patch. [1] https://lore.kernel.org/all/20260419014800.877-1-sj@kernel.org/ Thanks, SJ > > > + if (kdamond_pid < 0) > > + kdamond_pid = -1; > > + } > > + return sprintf(buffer, "%d\n", kdamond_pid); > > +} > > -- > Sashiko AI review · https://sashiko.dev/#/patchset/20260513043902.183499-1-sj@kernel.org?part=1 ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-05-14 5:35 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <2026051254-walrus-thrift-66bc@gregkh>
2026-05-13 4:39 ` [PATCH 6.18.y] mm/damon/reclaim: detect and use fresh enabled and kdamond_pid values SeongJae Park
2026-05-14 2:02 ` sashiko-bot
2026-05-14 5:35 ` SeongJae Park
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox