FAILED: patch "[PATCH] mm/damon/lru_sort: detect and use fresh enabled and" failed to apply to 6.18-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x b98b7ff6025ae82570d4915e083f0cbd8d48b3cf
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026051240-quickly-effective-c901@gregkh' --subject-prefix 'PATCH 6.18.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From b98b7ff6025ae82570d4915e083f0cbd8d48b3cf Mon Sep 17 00:00:00 2001
From: SeongJae Park <[email protected]>
Date: Sun, 19 Apr 2026 09:10:01 -0700
Subject: [PATCH] mm/damon/lru_sort: detect and use fresh enabled and
kdamond_pid values
DAMON_LRU_SORT 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_LRU_SORT 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_lru_sort/parameters
#
# # start DAMON_LRU_SORT
# 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 kdamondThe 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.
mm/damon/lru_sort.c +55 -30
@@ -161,15 +161,6 @@ module_param(monitor_region_end, ulong, 0600);*/ static unsigned long addr_unit__read_mostly =1 ; -/* -* PID of the DAMON thread -* -* If DAMON_LRU_SORT 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_lru_sort_hot_stat; DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_lru_sort_hot_stat, lru_sort_tried_hot_regions, lru_sorted_hot_regions,
@@ -386,12 +377,8 @@ static int damon_lru_sort_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_lru_sort_apply_parameters ();if (err)
@@ -400,9 +387,6 @@ static int damon_lru_sort_turn(bool on) err =damon_start (&ctx,1 , true);if (err)return err; - kdamond_pid =damon_kdamond_pid (ctx); -if (kdamond_pid <0 ) -return kdamond_pid;return damon_call (ctx, &call_control); }
@@ -430,42 +414,83 @@ module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600);MODULE_PARM_DESC (addr_unit,"Scale factor for DAMON_LRU_SORT to ops address conversion (default: 1)" ); +static bool damon_lru_sort_enabled (void ) +{ +if (!ctx) +return false; +return damon_is_running (ctx); +} +static int damon_lru_sort_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_lru_sort_enabled () == enabled)return 0 ;/* Called before init function. The function will handle this. */ if (!damon_initialized ()) - goto set_param_out; +return 0 ; - err =damon_lru_sort_turn (enable); -if (err) -return err; +return damon_lru_sort_turn (enabled); +} -set_param_out: - enabled = enable; -return err; +static int damon_lru_sort_enabled_load (char *buffer, +const struct kernel_param *kp) +{ +return sprintf (buffer,"%c\n" ,damon_lru_sort_enabled () ?'Y' :'N' ); }static const struct kernel_param_ops enabled_param_ops = { .set = damon_lru_sort_enabled_store, - .get = param_get_bool, + .get = damon_lru_sort_enabled_load, };module_param_cb (enabled, &enabled_param_ops, &enabled,0600 );MODULE_PARM_DESC (enabled,"Enable or disable DAMON_LRU_SORT (default: disabled)" ); +static int damon_lru_sort_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_lru_sort_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_lru_sort_kdamond_pid_store, + .get = damon_lru_sort_kdamond_pid_load, +}; + +/* +* PID of the DAMON thread +* +* If DAMON_LRU_SORT 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_lru_sort_init (void ) {int err;
SeongJae Park
maintainerPATCH 1/2 mm/damon/core: implement damon_kdamond_pid()
Patch series "mm/damon: hide kdamond and kdamond_lock from API callers".
'kdamond' and 'kdamond_lock' fields initially exposed to DAMON API callers for flexible synchronization and use cases. As DAMON API became somewhat complicated compared to the early days, Keeping those exposed could only encourage the API callers to invent more creative but complicated and difficult-to-debug use cases.
Fortunately DAMON API callers didn't invent that many creative use cases. There exist only two use cases of 'kdamond' and 'kdamond_lock'. Finding whether the kdamond is actively running, and getting the pid of the kdamond. For the first use case, a dedicated API function, namely 'damon_is_running()' is provided, and all DAMON API callers are using the function for the use case. Hence only the second use case is where the fields are directly being used by DAMON API callers.
To prevent future invention of complicated and erroneous use cases of the fields, hide the fields from the API callers. For that, provide new dedicated DAMON API functions for the remaining use case, namely damon_kdamond_pid(), migrate DAMON API callers to use the new function, and mark the fields as private fields.
This patch (of 5):
'kdamond' and 'kdamond_lock' are directly being used by DAMON API callers for getting the pid of the corresponding kdamond. To discourage invention of creative but complicated and erroneous new usages of the fields that require careful synchronization, implement a new API function that can simply be used without the manual synchronizations.
---
The second patch depends on this commit, so porting this together.
include/linux/damon.h | 1 + mm/damon/core.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+)
include/linux/damon.h +1 -0
@@ -949,6 +949,7 @@ bool damon_initialized(void);int damon_start (struct damon_ctx **ctxs,int nr_ctxs,bool exclusive);int damon_stop (struct damon_ctx **ctxs,int nr_ctxs);bool damon_is_running (struct damon_ctx *ctx); +int damon_kdamond_pid (struct damon_ctx *ctx);int damon_call (struct damon_ctx *ctx,struct damon_call_control *control);int damos_walk (struct damon_ctx *ctx,struct damos_walk_control *control);
mm/damon/core.c +17 -0
@@ -1431,6 +1431,23 @@ bool damon_is_running(struct damon_ctx *ctx)return running; } +/** +* damon_kdamond_pid() - Return pid of a given DAMON context's worker thread. +* @ctx: The DAMON context of the question. +* +* Return: pid if @ctx is running, negative error code otherwise. +*/ +int damon_kdamond_pid (struct damon_ctx *ctx) +{ +int pid = -EINVAL ; + +mutex_lock (&ctx->kdamond_lock); +if (ctx->kdamond) + pid = ctx->kdamond->pid; +mutex_unlock (&ctx->kdamond_lock); +return pid; +} +/** * damon_call() - Invoke a given function on DAMON worker thread (kdamond). * @ctx: DAMON context to call the function for.
Signature · 1 line
2.47.3
SeongJae Park
maintainerPATCH 2/2 mm/damon/lru_sort: detect and use fresh enabled and kdamond_pid values
In reply to [email protected]DAMON_LRU_SORT 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_LRU_SORT 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_lru_sort/parameters
#
# # start DAMON_LRU_SORT
# 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 kdamondThe 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.
--- mm/damon/lru_sort.c | 83 ++++++++++++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 28 deletions(-)
mm/damon/lru_sort.c +55 -28
@@ -118,15 +118,6 @@ module_param(monitor_region_end, ulong, 0600);*/ static unsigned long addr_unit__read_mostly =1 ; -/* -* PID of the DAMON thread -* -* If DAMON_LRU_SORT 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_lru_sort_hot_stat; DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_lru_sort_hot_stat, lru_sort_tried_hot_regions, lru_sorted_hot_regions,
@@ -288,12 +279,8 @@ static int damon_lru_sort_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_lru_sort_apply_parameters ();if (err)
@@ -302,7 +289,6 @@ static int damon_lru_sort_turn(bool on) err =damon_start (&ctx,1 , true);if (err)return err; - kdamond_pid = ctx->kdamond->pid;return damon_call (ctx, &call_control); }
@@ -330,42 +316,83 @@ module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600);MODULE_PARM_DESC (addr_unit,"Scale factor for DAMON_LRU_SORT to ops address conversion (default: 1)" ); +static bool damon_lru_sort_enabled (void ) +{ +if (!ctx) +return false; +return damon_is_running (ctx); +} +static int damon_lru_sort_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_lru_sort_enabled () == enabled)return 0 ;/* Called before init function. The function will handle this. */ if (!damon_initialized ()) - goto set_param_out; +return 0 ; - err =damon_lru_sort_turn (enable); -if (err) -return err; +return damon_lru_sort_turn (enabled); +} -set_param_out: - enabled = enable; -return err; +static int damon_lru_sort_enabled_load (char *buffer, +const struct kernel_param *kp) +{ +return sprintf (buffer,"%c\n" ,damon_lru_sort_enabled () ?'Y' :'N' ); }static const struct kernel_param_ops enabled_param_ops = { .set = damon_lru_sort_enabled_store, - .get = param_get_bool, + .get = damon_lru_sort_enabled_load, };module_param_cb (enabled, &enabled_param_ops, &enabled,0600 );MODULE_PARM_DESC (enabled,"Enable or disable DAMON_LRU_SORT (default: disabled)" ); +static int damon_lru_sort_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_lru_sort_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_lru_sort_kdamond_pid_store, + .get = damon_lru_sort_kdamond_pid_load, +}; + +/* +* PID of the DAMON thread +* +* If DAMON_LRU_SORT 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_lru_sort_init (void ) {int err;
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 6.18.y 2/2] mm/damon/lru_sort: detect and use fresh enabled and kdamond_pid values
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] NULL pointer dereference in damon_lru_sort_enabled_store if module initialization fails. --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] NULL pointer dereference in damon_lru_sort_enabled_store if module initialization fails. --
commit 1c4b8a292830197d1c3c21bb2ed871fd37b99120
Author: SeongJae Park <[email protected]>
mm/damon/lru_sort: detect and use fresh enabled and kdamond_pid values
This patch updates DAMON_LRU_SORT to dynamically detect and use the fresh status for the enabled and kdamond_pid parameters when requested. This avoids stale parameter values if kdamond is stopped unintentionally.
Quoted 4 lines
mm/damon/lru_sort.c +0
-0
[ ... ]
Quoted 26 lines
mm/damon/lru_sort.c +9
-4@@ -330,42 +316,83 @@ module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600);MODULE_PARM_DESC (addr_unit,"Scale factor for DAMON_LRU_SORT to ops address conversion (default: 1)" ); +static bool damon_lru_sort_enabled (void ) +{ +if (!ctx) +return false; +return damon_is_running (ctx); +} +static int damon_lru_sort_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_lru_sort_enabled () == enabled)return 0 ;
mm/damon/lru_sort.c module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600); · line 342
Quoted 10 lines
mm/damon/lru_sort.c +2
-4/* Called before init function. The function will handle this. */ if (!damon_initialized ()) - goto set_param_out; +return 0 ; - err =damon_lru_sort_turn (enable); -if (err) -return err; +return damon_lru_sort_turn (enabled);
Can this result in a NULL pointer dereference if the module initialization fails?
If damon_lru_sort_init() fails during boot (for instance, due to memory allocation failure), ctx remains NULL. Since CONFIG_DAMON_LRU_SORT parameters are registered as built-in module parameters, writing 'Y' to /sys/module/damon_lru_sort/parameters/enabled will invoke damon_lru_sort_enabled_store().
In this scenario:
- damon_lru_sort_enabled() safely returns false (due to !ctx).
- The damon_lru_sort_enabled() == enabled check is bypassed (false != true).
- damon_initialized() returns true (since the DAMON core initialized).
- damon_lru_sort_turn(true) is executed.
This leads to damon_lru_sort_apply_parameters() calling damon_commit_ctx(ctx, param_ctx), which unconditionally dereferences the NULL ctx, leading to a kernel panic.
Should there be an explicit if (!ctx) check in damon_lru_sort_enabled_store() to prevent this, similar to how it was added to the read paths?
While this vulnerability is not strictly introduced by this patch, the patch misses the opportunity to fix it while addressing ctx nullability in the read paths. The same vulnerability also appears to be present in sibling modules mm/damon/reclaim.c and mm/damon/stat.c.
Quoted 6 lines
mm/damon/lru_sort.c +1
-4+} -set_param_out: - enabled = enable; -return err; -}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/2026051240-quickly-effective-c901@gregkh?part=2
SeongJae Park
maintainerRe: [PATCH 6.18.y 2/2] mm/damon/lru_sort: detect and use fresh enabled and kdamond_pid values
Quoted 78 lines · On Thu, 14 May 2026 01:56:20 +0000 [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] NULL pointer dereference indamon_lru_sort_enabled_storeif module initialization fails. --commit
1c4b8a292830197d1c3c21bb2ed871fd37b99120
Author: SeongJae Park <[email protected]>
mm/damon/lru_sort: detect and use fresh enabled andkdamond_pidvaluesThis patch updates
DAMON_LRU_SORTto dynamically detect and use the fresh status for the enabled andkdamond_pidparameters when requested. This avoids stale parameter values if kdamond is stopped unintentionally.Quoted 4 lines
mm/damon/lru_sort.c +0
-0[ ... ]
Quoted 26 lines
mm/damon/lru_sort.c +9
-4@@ -330,42 +316,83 @@ module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600);MODULE_PARM_DESC (addr_unit,"Scale factor for DAMON_LRU_SORT to ops address conversion (default: 1)" ); +static bool damon_lru_sort_enabled (void ) +{ +if (!ctx) +return false; +return damon_is_running (ctx); +} +static int damon_lru_sort_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_lru_sort_enabled () == enabled)return 0 ;mm/damon/lru_sort.c module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600); · line 342
Quoted 10 lines
mm/damon/lru_sort.c +2
-4/* Called before init function. The function will handle this. */ if (!damon_initialized ()) - goto set_param_out; +return 0 ; - err =damon_lru_sort_turn (enable); -if (err) -return err; +return damon_lru_sort_turn (enabled);Can this result in a NULL pointer dereference if the module initialization fails?
If
damon_lru_sort_init()fails during boot (for instance, due to memory allocation failure), ctx remains NULL. SinceCONFIG_DAMON_LRU_SORTparameters are registered as built-in module parameters, writing 'Y' to/sys/module/damon_lru_sort/parameters/enabledwill invokedamon_lru_sort_enabled_store().In this scenario:
-damon_lru_sort_enabled()safely returns false (due to !ctx).
- Thedamon_lru_sort_enabled()== enabled check is bypassed (false != true).
-damon_initialized()returns true (since the DAMON core initialized).
-damon_lru_sort_turn(true)is executed.This leads to
damon_lru_sort_apply_parameters()callingdamon_commit_ctx(ctx, param_ctx), which unconditionally dereferences the NULL ctx, leading to a kernel panic.
Quoted 8 lines
Should there be an explicit if (!ctx) check in
damon_lru_sort_enabled_store()to prevent this, similar to how it was added to the read paths?While this vulnerability is not strictly introduced by this patch, the patch misses the opportunity to fix it while addressing ctx nullability in the read paths. The same vulnerability also appears to be present in sibling modules
mm/damon/reclaim.candmm/damon/stat.c.
Sashiko reported [1] same thing before, and I'm working on it.
[1] https://lore.kernel.org/all/[email protected]/
Thanks,
SJ
[...]