Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mm/util: Swap kmemdup_array() arguments

GCC 14.1 complains about the argument usage of kmemdup_array():

drivers/soc/tegra/fuse/fuse-tegra.c:130:65: error: 'kmemdup_array' sizes specified with 'sizeof' in the earlier argument and not in the later argument [-Werror=calloc-transposed-args]
130 | fuse->lookups = kmemdup_array(fuse->soc->lookups, sizeof(*fuse->lookups),
| ^
drivers/soc/tegra/fuse/fuse-tegra.c:130:65: note: earlier argument should specify number of elements, later size of each element

The annotation introduced by commit 7d78a7773355 ("string: Add
additional __realloc_size() annotations for "dup" helpers") lets the
compiler think that kmemdup_array() follows the same format as calloc(),
with the number of elements preceding the size of one element. So we
could simply swap the arguments to __realloc_size() to get rid of that
warning, but it seems cleaner to instead have kmemdup_array() follow the
same format as krealloc_array(), memdup_array_user(), calloc() etc.

Fixes: 7d78a7773355 ("string: Add additional __realloc_size() annotations for "dup" helpers")
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Link: https://lore.kernel.org/r/20240606144608.97817-2-jean-philippe@linaro.org
Signed-off-by: Kees Cook <kees@kernel.org>

authored by

Jean-Philippe Brucker and committed by
Kees Cook
0ee14725 c3f38fa6

+6 -6
+2 -2
drivers/soc/tegra/fuse/fuse-tegra.c
··· 127 127 128 128 static int tegra_fuse_add_lookups(struct tegra_fuse *fuse) 129 129 { 130 - fuse->lookups = kmemdup_array(fuse->soc->lookups, sizeof(*fuse->lookups), 131 - fuse->soc->num_lookups, GFP_KERNEL); 130 + fuse->lookups = kmemdup_array(fuse->soc->lookups, fuse->soc->num_lookups, 131 + sizeof(*fuse->lookups), GFP_KERNEL); 132 132 if (!fuse->lookups) 133 133 return -ENOMEM; 134 134
+1 -1
include/linux/string.h
··· 289 289 290 290 extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2); 291 291 extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp); 292 - extern void *kmemdup_array(const void *src, size_t element_size, size_t count, gfp_t gfp) 292 + extern void *kmemdup_array(const void *src, size_t count, size_t element_size, gfp_t gfp) 293 293 __realloc_size(2, 3); 294 294 295 295 /* lib/argv_split.c */
+1 -1
lib/fortify_kunit.c
··· 374 374 for (i = 0; i < ARRAY_SIZE(test_strs); i++) { \ 375 375 len = strlen(test_strs[i]); \ 376 376 KUNIT_EXPECT_EQ(test, __builtin_constant_p(len), 0); \ 377 - checker(len, kmemdup_array(test_strs[i], len, 1, gfp), \ 377 + checker(len, kmemdup_array(test_strs[i], 1, len, gfp), \ 378 378 kfree(p)); \ 379 379 checker(len, kmemdup(test_strs[i], len, gfp), \ 380 380 kfree(p)); \
+2 -2
mm/util.c
··· 139 139 * kmemdup_array - duplicate a given array. 140 140 * 141 141 * @src: array to duplicate. 142 - * @element_size: size of each element of array. 143 142 * @count: number of elements to duplicate from array. 143 + * @element_size: size of each element of array. 144 144 * @gfp: GFP mask to use. 145 145 * 146 146 * Return: duplicated array of @src or %NULL in case of error, 147 147 * result is physically contiguous. Use kfree() to free. 148 148 */ 149 - void *kmemdup_array(const void *src, size_t element_size, size_t count, gfp_t gfp) 149 + void *kmemdup_array(const void *src, size_t count, size_t element_size, gfp_t gfp) 150 150 { 151 151 return kmemdup(src, size_mul(element_size, count), gfp); 152 152 }