Skip to content

Commit

Permalink
ida: Free allocated bitmap in error path
Browse files Browse the repository at this point in the history
[ 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>
  • Loading branch information
Matthew Wilcox (Oracle) authored and gregkh committed Oct 29, 2020
1 parent 3789f5c commit 2577720
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/idr.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ int ida_alloc_range(struct ida *ida, unsigned int min, unsigned int max,
goto retry;
nospc:
xas_unlock_irqrestore(&xas, flags);
kfree(alloc);
return -ENOSPC;
}
EXPORT_SYMBOL(ida_alloc_range);
Expand Down
29 changes: 29 additions & 0 deletions tools/testing/radix-tree/idr-test.c
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,27 @@ static void *ida_random_fn(void *arg)
return NULL;
}

static void *ida_leak_fn(void *arg)
{
struct ida *ida = arg;
time_t s = time(NULL);
int i, ret;

rcu_register_thread();

do for (i = 0; i < 1000; i++) {
ret = ida_alloc_range(ida, 128, 128, GFP_KERNEL);
if (ret >= 0)
ida_free(ida, 128);
} while (time(NULL) < s + 2);

rcu_unregister_thread();
return NULL;
}

void ida_thread_tests(void)
{
DEFINE_IDA(ida);
pthread_t threads[20];
int i;

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

while (i--)
pthread_join(threads[i], NULL);

for (i = 0; i < ARRAY_SIZE(threads); i++)
if (pthread_create(&threads[i], NULL, ida_leak_fn, &ida)) {
perror("creating ida thread");
exit(1);
}

while (i--)
pthread_join(threads[i], NULL);
assert(ida_is_empty(&ida));
}

void ida_tests(void)
Expand Down

0 comments on commit 2577720

Please sign in to comment.