summaryrefslogtreecommitdiff
path: root/drivers/md
diff options
context:
space:
mode:
authorBenjamin Marzinski <bmarzins@redhat.com>2025-04-15 00:17:16 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-05-09 09:43:52 +0200
commit64e95bb37916ab03dcb7a920276c5a52df8e568b (patch)
tree280fb32f0839c02930845b220e373e7db6435251 /drivers/md
parentecc7f159d17e6f15a67f5fee98f17575dcfcbb3d (diff)
downloadlinux-64e95bb37916ab03dcb7a920276c5a52df8e568b.tar.gz
linux-64e95bb37916ab03dcb7a920276c5a52df8e568b.tar.bz2
linux-64e95bb37916ab03dcb7a920276c5a52df8e568b.zip
dm: always update the array size in realloc_argv on success
commit 5a2a6c428190f945c5cbf5791f72dbea83e97f66 upstream. realloc_argv() was only updating the array size if it was called with old_argv already allocated. The first time it was called to create an argv array, it would allocate the array but return the array size as zero. dm_split_args() would think that it couldn't store any arguments in the array and would call realloc_argv() again, causing it to reallocate the initial slots (this time using GPF_KERNEL) and finally return a size. Aside from being wasteful, this could cause deadlocks on targets that need to process messages without starting new IO. Instead, realloc_argv should always update the allocated array size on success. Fixes: a0651926553c ("dm table: don't copy from a NULL pointer in realloc_argv()") Cc: stable@vger.kernel.org Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-table.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index fd84e06670e8..c32ae18a8ca3 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -500,9 +500,10 @@ static char **realloc_argv(unsigned int *size, char **old_argv)
gfp = GFP_NOIO;
}
argv = kmalloc_array(new_size, sizeof(*argv), gfp);
- if (argv && old_argv) {
- memcpy(argv, old_argv, *size * sizeof(*argv));
+ if (argv) {
*size = new_size;
+ if (old_argv)
+ memcpy(argv, old_argv, *size * sizeof(*argv));
}
kfree(old_argv);