Users can set damos_quota_goal->nid with arbitrary value for
node_mem_{used,free}_bp. But DAMON core is using those for
si_meminfo_node() without the 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 ./damo start --damos_action stat \
--damos_quota_goal node_mem_used_bp 50% -1 \
--damos_quota_interval 1s
$ sudo dmesg
[...]
[ 65.565986] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000098
Fix this issue by adding the validation of the given node. If an
invalid node id is given, it returns 0% for used memory ratio, and 100%
for free memory ratio.
Fixes: 0e1c773b501f ("mm/damon/core: introduce damos quota goal metrics for memory node utilization")
Cc: <stable@vger.kernel.org> # 6.16.x
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index ddabb93f2377..9a848d7647ef 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2217,12 +2217,24 @@ static inline u64 damos_get_some_mem_psi_total(void)
#endif /* CONFIG_PSI */
#ifdef CONFIG_NUMA
+static bool invalid_mem_node(int nid)
+{
+ return nid < 0 || nid >= MAX_NUMNODES || !node_state(nid, N_MEMORY);
+}
+
static __kernel_ulong_t damos_get_node_mem_bp(
struct damos_quota_goal *goal)
{
struct sysinfo i;
__kernel_ulong_t numerator;
+ if (invalid_mem_node(goal->nid)) {
+ if (goal->metric == DAMOS_QUOTA_NODE_MEM_USED_BP)
+ return 0;
+ else /* DAMOS_QUOTA_NODE_MEM_FREE_BP */
+ return 10000;
+ }
+
si_meminfo_node(&i, goal->nid);
if (goal->metric == DAMOS_QUOTA_NODE_MEM_USED_BP)
numerator = i.totalram - i.freeram;
--
2.47.3
Forwarding Sashiko review for doing discussions via mails.
# review url: https://sashiko.dev/#/patchset/20260329043902.46163-2-sj@kernel.org
# start of sashiko.dev inline review
commit 8c40c45c57722526c25cf1114b386d19a693fc2d
Author: SeongJae Park <sj@kernel.org>
mm/damon/core: validate damos_quota_goal->nid for node_mem_{used,free}_bp
This commit adds validation for the node ID in damos_quota_goal to prevent
out of bounds memory access when calling si_meminfo_node(). If an invalid
node ID is given, it defaults to returning 0% for used memory and 100% for
free memory.
> diff --git a/mm/damon/core.c b/mm/damon/core.c
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
[ ... ]
> static __kernel_ulong_t damos_get_node_mem_bp(
> struct damos_quota_goal *goal)
> {
> struct sysinfo i;
> __kernel_ulong_t numerator;
>
> + if (invalid_mem_node(goal->nid)) {
> + if (goal->metric == DAMOS_QUOTA_NODE_MEM_USED_BP)
> + return 0;
> + else /* DAMOS_QUOTA_NODE_MEM_FREE_BP */
> + return 10000;
> + }
> +
> si_meminfo_node(&i, goal->nid);
> if (goal->metric == DAMOS_QUOTA_NODE_MEM_USED_BP)
> numerator = i.totalram - i.freeram;
> else /* DAMOS_QUOTA_NODE_MEM_FREE_BP */
> numerator = i.freeram;
> return mult_frac(numerator, 10000, i.totalram);
Does this code still risk a divide-by-zero kernel panic if a memory node
has zero managed pages?
Even with the new invalid_mem_node() check ensuring node_state(nid, N_MEMORY)
is true, a memory node can have present physical pages but zero managed pages
if all its memory is reserved early in boot (for example, via memblock_reserve
for crash kernels or firmware).
In this scenario, si_meminfo_node() sets i.totalram to 0. Since the
mult_frac() macro directly evaluates division and modulo, passing
i.totalram as 0 will cause a hardware divide-by-zero exception.
Should there be an explicit check for i.totalram == 0 before calling
mult_frac() here and in other similar quota functions like
damos_get_node_memcg_used_bp()?
# end of sashiko.dev inline review
# review url: https://sashiko.dev/#/patchset/20260329043902.46163-2-sj@kernel.org
#
# hkml [1] generated a draft of this mail. It can be regenerated
# using below command:
#
# hkml patch sashiko_dev --for_forwarding \
# 20260329043902.46163-2-sj@kernel.org
#
# [1] https://github.com/sjp38/hackermail
Sent using hkml (https://github.com/sjp38/hackermail)
On Sun, 29 Mar 2026 08:34:06 -0700 SeongJae Park <sj@kernel.org> wrote:
> Forwarding Sashiko review for doing discussions via mails.
>
> # review url: https://sashiko.dev/#/patchset/20260329043902.46163-2-sj@kernel.org
> # start of sashiko.dev inline review
> commit 8c40c45c57722526c25cf1114b386d19a693fc2d
> Author: SeongJae Park <sj@kernel.org>
>
> mm/damon/core: validate damos_quota_goal->nid for node_mem_{used,free}_bp
>
> This commit adds validation for the node ID in damos_quota_goal to prevent
> out of bounds memory access when calling si_meminfo_node(). If an invalid
> node ID is given, it defaults to returning 0% for used memory and 100% for
> free memory.
>
> > diff --git a/mm/damon/core.c b/mm/damon/core.c
> > --- a/mm/damon/core.c
> > +++ b/mm/damon/core.c
>
> [ ... ]
>
> > static __kernel_ulong_t damos_get_node_mem_bp(
> > struct damos_quota_goal *goal)
> > {
> > struct sysinfo i;
> > __kernel_ulong_t numerator;
> >
> > + if (invalid_mem_node(goal->nid)) {
> > + if (goal->metric == DAMOS_QUOTA_NODE_MEM_USED_BP)
> > + return 0;
> > + else /* DAMOS_QUOTA_NODE_MEM_FREE_BP */
> > + return 10000;
> > + }
> > +
> > si_meminfo_node(&i, goal->nid);
> > if (goal->metric == DAMOS_QUOTA_NODE_MEM_USED_BP)
> > numerator = i.totalram - i.freeram;
> > else /* DAMOS_QUOTA_NODE_MEM_FREE_BP */
> > numerator = i.freeram;
> > return mult_frac(numerator, 10000, i.totalram);
>
> Does this code still risk a divide-by-zero kernel panic if a memory node
> has zero managed pages?
>
> Even with the new invalid_mem_node() check ensuring node_state(nid, N_MEMORY)
> is true, a memory node can have present physical pages but zero managed pages
> if all its memory is reserved early in boot (for example, via memblock_reserve
> for crash kernels or firmware).
>
> In this scenario, si_meminfo_node() sets i.totalram to 0. Since the
> mult_frac() macro directly evaluates division and modulo, passing
> i.totalram as 0 will cause a hardware divide-by-zero exception.
>
> Should there be an explicit check for i.totalram == 0 before calling
> mult_frac() here and in other similar quota functions like
> damos_get_node_memcg_used_bp()?
As I mentioned to same previous comment, that's another bug that require
another patch. I will work on it with a separate patch.
Thanks,
SJ
[...]
© 2016 - 2026 Red Hat, Inc.