mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-11 00:50:21 +00:00
idr: fix idr_alloc() returning an ID out of range
If you use an IDR with a non-zero base, and specify a range that lies entirely below the base, 'max - base' becomes very large and idr_get_free() can return an ID that lies outside of the requested range. Link: https://lkml.kernel.org/r/20251128161853.3200058-1-willy@infradead.org Fixes: 6ce711f27500 ("idr: Make 1-based IDRs more efficient") Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Reported-by: Jan Sokolowski <jan.sokolowski@intel.com> Reported-by: Koen Koning <koen.koning@intel.com> Reported-by: Peter Senna Tschudin <peter.senna@linux.intel.com> Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/6449 Reviewed-by: Christian König <christian.koenig@amd.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
87726567d8
commit
c6e8e595a0
@ -40,6 +40,8 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid,
|
||||
|
||||
if (WARN_ON_ONCE(!(idr->idr_rt.xa_flags & ROOT_IS_IDR)))
|
||||
idr->idr_rt.xa_flags |= IDR_RT_MARKER;
|
||||
if (max < base)
|
||||
return -ENOSPC;
|
||||
|
||||
id = (id < base) ? 0 : id - base;
|
||||
radix_tree_iter_init(&iter, id);
|
||||
|
||||
@ -57,6 +57,26 @@ void idr_alloc_test(void)
|
||||
idr_destroy(&idr);
|
||||
}
|
||||
|
||||
void idr_alloc2_test(void)
|
||||
{
|
||||
int id;
|
||||
struct idr idr = IDR_INIT_BASE(idr, 1);
|
||||
|
||||
id = idr_alloc(&idr, idr_alloc2_test, 0, 1, GFP_KERNEL);
|
||||
assert(id == -ENOSPC);
|
||||
|
||||
id = idr_alloc(&idr, idr_alloc2_test, 1, 2, GFP_KERNEL);
|
||||
assert(id == 1);
|
||||
|
||||
id = idr_alloc(&idr, idr_alloc2_test, 0, 1, GFP_KERNEL);
|
||||
assert(id == -ENOSPC);
|
||||
|
||||
id = idr_alloc(&idr, idr_alloc2_test, 0, 2, GFP_KERNEL);
|
||||
assert(id == -ENOSPC);
|
||||
|
||||
idr_destroy(&idr);
|
||||
}
|
||||
|
||||
void idr_replace_test(void)
|
||||
{
|
||||
DEFINE_IDR(idr);
|
||||
@ -409,6 +429,7 @@ void idr_checks(void)
|
||||
|
||||
idr_replace_test();
|
||||
idr_alloc_test();
|
||||
idr_alloc2_test();
|
||||
idr_null_test();
|
||||
idr_nowait_test();
|
||||
idr_get_next_test(0);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user