CVE-2026-46067
Description
In the Linux kernel, the following vulnerability has been resolved:
mm/damon/core: validate damos_quota_goal->nid for node_memcg_{used,free}_bp
Users can set damos_quota_goal->nid with arbitrary value for node_memcg_{used,free}_bp. But DAMON core is using those for NODE-DATA() without a validation of the value. This can result in out of bounds memory access. The issue can actually triggered using DAMON user-space tool (damo), like below.
$ sudo mkdir /sys/fs/cgroup/foo $ sudo ./damo start --damos_action stat --damos_quota_interval 1s \ --damos_quota_goal node_memcg_used_bp 50% -1 /foo $ sudo dmseg [...] [ 524.181426] Unable to handle kernel paging request at virtual address 0000000000002c00
Fix this issue by adding the validation of the given node id. If an invalid node id is given, it returns 0% for used memory ratio, and 100% for free memory ratio.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Missing validation of user-supplied node ID in DAMON quota goal (node_memcg_{used,free}_bp) causes out-of-bounds memory access, enabling a local DoS via damo tool.
Vulnerability
In the Linux kernel's mm/damon/core subsystem, the damos_quota_goal structure allows users to set the nid field arbitrarily when using quota goal types node_memcg_used_bp or node_memcg_free_bp. The code passes this user-supplied value directly to NODE_DATA() without validation, leading to an out-of-bounds memory access. This issue affects kernel versions prior to the commit da10db73ada26345244ea5dc52f974692bd05f66 [1].
Exploitation
An attacker with local access can use the DAMON user-space tool damo to trigger the vulnerability. For example, by running: sudo ./damo start --damos_action stat --damos_quota_interval 1s --damos_quota_goal node_memcg_used_bp 50% -1 /foo and supplying an invalid node ID (-1), the kernel crashes with an Unable to handle kernel paging request [1]. No special privileges beyond sudo (or equivalent capabilities for DAMON control) are required; the attacker only needs write access to the DAMON control interface.
Impact
Successful exploitation results in a kernel crash (denial of service) due to an out-of-bounds memory access when the kernel dereferences NODE_DATA(-1). This can cause system instability or a complete system hang. Confidentiality and integrity are not directly compromised; the primary impact is availability loss [1].
Mitigation
The fix is included in Linux kernel commit da10db73ada26345244ea5dc52f974692bd05f66 [1]. Users should update to a kernel version containing this commit or apply the patch. No workaround is available; the only mitigation is to apply the kernel update once released.
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
4da10db73ada2mm/damon/core: validate damos_quota_goal->nid for node_memcg_{used,free}_bp
2 files changed · +14 −2
mm/damon/core.c+7 −1 modifieddiff --git a/mm/damon/core.c b/mm/damon/core.c index 1a447dd0c05338..cedda7efd95720 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2112,6 +2112,13 @@ static unsigned long damos_get_node_memcg_used_bp( unsigned long used_pages, numerator; struct sysinfo i; + if (invalid_mem_node(goal->nid)) { + if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) + return 0; + else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ + return 10000; + } + memcg = mem_cgroup_get_from_id(goal->memcg_id); if (!memcg) { if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) -- cgit 1.3-korg
mm/damon/core.c+7 −1 modifieddiff --git a/mm/damon/core.c b/mm/damon/core.c index 1a447dd0c05338..cedda7efd95720 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2112,6 +2112,13 @@ static unsigned long damos_get_node_memcg_used_bp( unsigned long used_pages, numerator; struct sysinfo i; + if (invalid_mem_node(goal->nid)) { + if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) + return 0; + else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ + return 10000; + } + memcg = mem_cgroup_get_from_id(goal->memcg_id); if (!memcg) { if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) -- cgit 1.3-korg
a34dac6482e5mm/damon/core: validate damos_quota_goal->nid for node_memcg_{used,free}_bp
2 files changed · +14 −2
mm/damon/core.c+7 −1 modifieddiff --git a/mm/damon/core.c b/mm/damon/core.c index 9a848d7647ef9e..19642c17556890 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2251,6 +2251,13 @@ static unsigned long damos_get_node_memcg_used_bp( unsigned long used_pages, numerator; struct sysinfo i; + if (invalid_mem_node(goal->nid)) { + if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) + return 0; + else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ + return 10000; + } + memcg = mem_cgroup_get_from_id(goal->memcg_id); if (!memcg) { if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) -- cgit 1.3-korg
mm/damon/core.c+7 −1 modifieddiff --git a/mm/damon/core.c b/mm/damon/core.c index 9a848d7647ef9e..19642c17556890 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2251,6 +2251,13 @@ static unsigned long damos_get_node_memcg_used_bp( unsigned long used_pages, numerator; struct sysinfo i; + if (invalid_mem_node(goal->nid)) { + if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) + return 0; + else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ + return 10000; + } + memcg = mem_cgroup_get_from_id(goal->memcg_id); if (!memcg) { if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) -- cgit 1.3-korg
a34dac6482e5mm/damon/core: validate damos_quota_goal->nid for node_memcg_{used,free}_bp
2 files changed · +14 −2
mm/damon/core.c+7 −1 modifieddiff --git a/mm/damon/core.c b/mm/damon/core.c index 9a848d7647ef9e..19642c17556890 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2251,6 +2251,13 @@ static unsigned long damos_get_node_memcg_used_bp( unsigned long used_pages, numerator; struct sysinfo i; + if (invalid_mem_node(goal->nid)) { + if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) + return 0; + else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ + return 10000; + } + memcg = mem_cgroup_get_from_id(goal->memcg_id); if (!memcg) { if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) -- cgit 1.3-korg
mm/damon/core.c+7 −1 modifieddiff --git a/mm/damon/core.c b/mm/damon/core.c index 9a848d7647ef9e..19642c17556890 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2251,6 +2251,13 @@ static unsigned long damos_get_node_memcg_used_bp( unsigned long used_pages, numerator; struct sysinfo i; + if (invalid_mem_node(goal->nid)) { + if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) + return 0; + else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ + return 10000; + } + memcg = mem_cgroup_get_from_id(goal->memcg_id); if (!memcg) { if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) -- cgit 1.3-korg
da10db73ada2mm/damon/core: validate damos_quota_goal->nid for node_memcg_{used,free}_bp
2 files changed · +14 −2
mm/damon/core.c+7 −1 modifieddiff --git a/mm/damon/core.c b/mm/damon/core.c index 1a447dd0c05338..cedda7efd95720 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2112,6 +2112,13 @@ static unsigned long damos_get_node_memcg_used_bp( unsigned long used_pages, numerator; struct sysinfo i; + if (invalid_mem_node(goal->nid)) { + if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) + return 0; + else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ + return 10000; + } + memcg = mem_cgroup_get_from_id(goal->memcg_id); if (!memcg) { if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) -- cgit 1.3-korg
mm/damon/core.c+7 −1 modifieddiff --git a/mm/damon/core.c b/mm/damon/core.c index 1a447dd0c05338..cedda7efd95720 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -2112,6 +2112,13 @@ static unsigned long damos_get_node_memcg_used_bp( unsigned long used_pages, numerator; struct sysinfo i; + if (invalid_mem_node(goal->nid)) { + if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) + return 0; + else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ + return 10000; + } + memcg = mem_cgroup_get_from_id(goal->memcg_id); if (!memcg) { if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP) -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing validation of damos_quota_goal->nid allows out-of-bounds memory access via NODE-DATA() macro."
Attack vector
An attacker with local access can use the DAMON user-space tool (damo) to set damos_quota_goal->nid to an arbitrary value (e.g., -1) when using the node_memcg_used_bp or node_memcg_free_bp quota goal metrics. The kernel passes this unchecked value to the NODE-DATA() macro, which indexes into an array, causing an out-of-bounds memory access. The commit message demonstrates triggering this by running `sudo ./damo start --damos_action stat --damos_quota_interval 1s --damos_quota_goal node_memcg_used_bp 50% -1 /foo`, which results in a kernel paging request fault.
Affected code
The vulnerable code is in the `damos_get_node_memcg_used_bp()` function in `mm/damon/core.c` [patch_id=2659988][patch_id=2659989]. The function uses `goal->nid` in the NODE-DATA() macro without validating that the node ID is within valid bounds.
What the fix does
The patch adds a call to `invalid_mem_node(goal->nid)` at the top of `damos_get_node_memcg_used_bp()` in `mm/damon/core.c` [patch_id=2659988][patch_id=2659989]. If the node ID is invalid, the function returns early: 0 for used-memory ratio (DAMOS_QUOTA_NODE_MEMCG_USED_BP) and 10000 (100%) for free-memory ratio (DAMOS_QUOTA_NODE_MEMCG_FREE_BP). This prevents the invalid node ID from ever reaching the NODE-DATA() macro, closing the out-of-bounds access path.
Preconditions
- authAttacker needs local access with sufficient privileges to run the damo tool (requires sudo).
- configThe DAMON kernel feature must be enabled and the damo user-space tool must be installed.
- inputAttacker must supply an invalid node ID (e.g., -1) via the --damos_quota_goal parameter.
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
2News mentions
0No linked articles in our index yet.