]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
pinctrl: devicetree: don't free uninitialized dev_name on error path
authorKarl Mehltretter <kmehltretter@gmail.com>
Sun, 19 Jul 2026 12:11:40 +0000 (14:11 +0200)
committerLinus Walleij <linusw@kernel.org>
Sat, 25 Jul 2026 09:17:23 +0000 (11:17 +0200)
dt_remember_or_free_map() duplicates dev_name for each map entry. If
kstrdup_const() fails, dt_free_map() frees dev_name in all num_maps
entries, including entries that have not been initialized.

Some pinctrl drivers, including pinctrl-imx, allocate the map with
kmalloc() and leave dev_name for the core to initialize. The untouched
entries therefore contain uninitialized data which is passed to
kfree_const().

Reproduced on qemu's mcimx6ul-evk (pinctrl-imx) with failslab injection
while binding the pinctrl-consuming device, under KASAN:

  BUG: KASAN: double-free in dt_free_map+0x34/0xa4
  Free of addr c425a900 by task init/1
   kfree from dt_free_map+0x34/0xa4
   dt_free_map from dt_remember_or_free_map+0x184/0x198
   dt_remember_or_free_map from pinctrl_dt_to_map+0x33c/0x4c8
   pinctrl_dt_to_map from create_pinctrl+0x9c/0x5c0

Initialize all dev_name fields to NULL before duplicating the device
name, making the full-map cleanup safe after a partial failure.

Fixes: be4c60b563ed ("pinctrl: devicetree: Avoid taking direct reference to device name string")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-fable-5
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
Signed-off-by: Linus Walleij <linusw@kernel.org>
drivers/pinctrl/devicetree.c

index 02a271dd292f2bd6efe4872f9b81a887f6a11326..465b43092eb76357ca42a69bf89b659fc5e8118b 100644 (file)
@@ -69,6 +69,10 @@ static int dt_remember_or_free_map(struct pinctrl *p, const char *statename,
        int i;
        struct pinctrl_dt_map *dt_map;
 
+       /* Initialize dev_name before any allocation can fail */
+       for (i = 0; i < num_maps; i++)
+               map[i].dev_name = NULL;
+
        /* Initialize common mapping table entry fields */
        for (i = 0; i < num_maps; i++) {
                const char *devname;