Skip to content

Commit 6ce0db9

Browse files
sjp38gregkh
authored andcommitted
mm/damon/core: disallow overlapping input ranges for damon_set_regions()
commit 9541576 upstream. damon_set_regions() assumes the input ranges are sorted by the address and don't overlap each other. Hence the assumption was initially to be explicitly validated. But commit 97d482f ("mm/damon/sysfs: reuse damon_set_regions() for regions setting") has mistakenly removed the validation. This can make DAMON behave in unexpected ways. At the best, the monitoring results snapshot will just look weird since there will be overlapping regions. DAMOS will also work weirdly, applying the same action multiple times for overlapping regions, and make DAMOS quota weird. More seriously, depending on the setup and regions updates sequence, negative size regions can be made. It will trigger WARN_ONCE() if the kernel is built with CONFIG_DAMON_DEBUG_SANITY=y. Depending on the monitoring results, the negative size region can further trigger division by zero in damon_merge_two_regions(). Note that some of the consequences including the WARN_ONCE() and the divide by zero depend on commits that were introduced after the root cause commit 97d482f ("mm/damon/sysfs: reuse damon_set_regions() for regions setting"). Fix the problems by checking the assumption and returning an error if the input ranges don't meet the assumption. The issue was discovered [1] by Sashiko. Link: https://lore.kernel.org/20260703165610.92894-1-sj@kernel.org Link: https://lore.kernel.org/20260630041806.151124-1-sj@kernel.org [1] Fixes: 97d482f ("mm/damon/sysfs: reuse damon_set_regions() for regions setting") Signed-off-by: SJ Park <sj@kernel.org> Cc: <stable@vger.kernel.org> # 5.19.x Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: SJ Park <sj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 4b6f1d6 commit 6ce0db9

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

mm/damon/core.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,12 +213,19 @@ int damon_set_regions(struct damon_target *t, struct damon_addr_range *ranges,
213213
{
214214
struct damon_region *r, *next;
215215
unsigned int i;
216+
unsigned long last_end;
216217
int err;
217218

218219
for (i = 0; i < nr_ranges; i++) {
219-
if (ALIGN_DOWN(ranges[i].start, min_sz_region) >=
220-
ALIGN(ranges[i].end, min_sz_region))
220+
unsigned long start, end;
221+
222+
start = ALIGN_DOWN(ranges[i].start, min_sz_region);
223+
end = ALIGN(ranges[i].end, min_sz_region);
224+
if (start >= end)
225+
return -EINVAL;
226+
if (i > 0 && last_end > start)
221227
return -EINVAL;
228+
last_end = end;
222229
}
223230

224231
/* Remove regions which are not in the new ranges */

0 commit comments

Comments
 (0)