]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mm/damon/core: validate ranges in damon_set_regions()
authorSJ Park <sj@kernel.org>
Tue, 30 Jun 2026 03:52:19 +0000 (20:52 -0700)
committerAndrew Morton <akpm@linux-foundation.org>
Thu, 9 Jul 2026 22:48:54 +0000 (15:48 -0700)
DAMON core logic assumes zero length regions don't exist.  However, a few
DAMON API callers including DAMON_SYSFS, DAMON_RECLAIM and DAMON_LRU_SORT
allow users to set empty monitoring target regions.  This could result in
WARN_ONCE() on CONFIG_DAMON_DEBUG_SANITY enabled kernel, and
divide-by-zero from damon_merge_two_regions().

For example, the WANR_ONCE() can be triggered like below.

    # grep DAMON_DEBUG_SANITY /boot/config-$(uname -r)
    # CONFIG_DAMON_DEBUG_SANITY=y
    # damo start
    # cd /sys/kernel/mm/damon/admin/kdamonds/0
    # echo 0 > contexts/0/targets/0/regions/0/start
    # echo 0 > contexts/0/targets/0/regions/0/end
    # echo commit > state
    # dmesg
    [....]
    [   73.705780] ------------[ cut here ]------------
    [   73.707552] start 0 >= end 0
    [   73.708452] WARNING: mm/damon/core.c:359 at damon_new_region+0x6e/0x80, CPU#1: kdamond.0/758
    [...]

All DAMON API callers eventually use damon_set_regions() to setup the
regions.  Add the validation logic in the function.

Link: https://lore.kernel.org/20260630035221.146458-1-sj@kernel.org
Fixes: 43b0536cb471 ("mm/damon: introduce DAMON-based Reclamation (DAMON_RECLAIM)")
Signed-off-by: SJ Park <sj@kernel.org>
Cc: Yang yingliang <yangyingliang@huawei.com>
Cc: <stable@vger.kernel.org> # 5.16.x
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/damon/core.c

index d99f7a297fdde6b6f90abfa79a1eb7441c5a145a..949d5309d54d3ec59652171dd56749abc7ab777b 100644 (file)
@@ -356,6 +356,12 @@ int damon_set_regions(struct damon_target *t, struct damon_addr_range *ranges,
        unsigned int i;
        int err;
 
+       for (i = 0; i < nr_ranges; i++) {
+               if (ALIGN_DOWN(ranges[i].start, min_region_sz) >=
+                               ALIGN(ranges[i].end, min_region_sz))
+                       return -EINVAL;
+       }
+
        /* Remove regions which are not in the new ranges */
        damon_for_each_region_safe(r, next, t) {
                for (i = 0; i < nr_ranges; i++) {