Skip to content

Commit cc3a03c

Browse files
Matthew Wilcox (Oracle)gregkh
authored andcommitted
ida: Free allocated bitmap in error path
[ Upstream commit a219b85 ] If a bitmap needs to be allocated, and then by the time the thread is scheduled to be run again all the indices which would satisfy the allocation have been allocated then we would leak the allocation. Almost impossible to hit in practice, but a trivial fix. Found by Coverity. Fixes: f32f004 ("ida: Convert to XArray") Reported-by: coverity-bot <keescook+coverity-bot@chromium.org> Reviewed-by: Kees Cook <keescook@chromium.org> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 0ee5ef9 commit cc3a03c

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

lib/idr.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ int ida_alloc_range(struct ida *ida, unsigned int min, unsigned int max,
470470
goto retry;
471471
nospc:
472472
xas_unlock_irqrestore(&xas, flags);
473+
kfree(alloc);
473474
return -ENOSPC;
474475
}
475476
EXPORT_SYMBOL(ida_alloc_range);

tools/testing/radix-tree/idr-test.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,27 @@ static void *ida_random_fn(void *arg)
523523
return NULL;
524524
}
525525

526+
static void *ida_leak_fn(void *arg)
527+
{
528+
struct ida *ida = arg;
529+
time_t s = time(NULL);
530+
int i, ret;
531+
532+
rcu_register_thread();
533+
534+
do for (i = 0; i < 1000; i++) {
535+
ret = ida_alloc_range(ida, 128, 128, GFP_KERNEL);
536+
if (ret >= 0)
537+
ida_free(ida, 128);
538+
} while (time(NULL) < s + 2);
539+
540+
rcu_unregister_thread();
541+
return NULL;
542+
}
543+
526544
void ida_thread_tests(void)
527545
{
546+
DEFINE_IDA(ida);
528547
pthread_t threads[20];
529548
int i;
530549

@@ -536,6 +555,16 @@ void ida_thread_tests(void)
536555

537556
while (i--)
538557
pthread_join(threads[i], NULL);
558+
559+
for (i = 0; i < ARRAY_SIZE(threads); i++)
560+
if (pthread_create(&threads[i], NULL, ida_leak_fn, &ida)) {
561+
perror("creating ida thread");
562+
exit(1);
563+
}
564+
565+
while (i--)
566+
pthread_join(threads[i], NULL);
567+
assert(ida_is_empty(&ida));
539568
}
540569

541570
void ida_tests(void)

0 commit comments

Comments
 (0)