]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mtd: slram: remove failed entries from the device list
authorRuoyu Wang <ruoyuw560@gmail.com>
Tue, 9 Jun 2026 08:45:27 +0000 (16:45 +0800)
committerMiquel Raynal <miquel.raynal@bootlin.com>
Thu, 11 Jun 2026 07:20:39 +0000 (09:20 +0200)
register_device() links a new slram_mtdlist entry before allocating all
of the state needed by the entry. If a later allocation, memremap(), or
mtd_device_register() fails, the partially initialized entry remains on
the global list. A later cleanup can then dereference or free invalid
state from that failed entry.

Unwind the partially initialized entry and clear the list tail on each
failure path after the entry has been linked.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
drivers/mtd/devices/slram.c

index 69cb63d99f57352fef7dba02804608b26ef73864..48c2bc6b65eec3a91047d10677a5a7d7b4292566 100644 (file)
@@ -129,6 +129,7 @@ static int slram_write(struct mtd_info *mtd, loff_t to, size_t len,
 static int register_device(char *name, unsigned long start, unsigned long length)
 {
        slram_mtd_list_t **curmtd;
+       int ret = -ENOMEM;
 
        curmtd = &slram_mtdlist;
        while (*curmtd) {
@@ -155,14 +156,15 @@ static int register_device(char *name, unsigned long start, unsigned long length
 
        if (!(*curmtd)->mtdinfo) {
                E("slram: Cannot allocate new MTD device.\n");
-               return(-ENOMEM);
+               goto err_free_list;
        }
 
        if (!(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start =
                memremap(start, length,
                         MEMREMAP_WB | MEMREMAP_WT | MEMREMAP_WC))) {
                E("slram: memremap failed\n");
-               return -EIO;
+               ret = -EIO;
+               goto err_free_priv;
        }
        ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end =
                ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start + length;
@@ -183,10 +185,8 @@ static int register_device(char *name, unsigned long start, unsigned long length
 
        if (mtd_device_register((*curmtd)->mtdinfo, NULL, 0))   {
                E("slram: Failed to register new device\n");
-               memunmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start);
-               kfree((*curmtd)->mtdinfo->priv);
-               kfree((*curmtd)->mtdinfo);
-               return(-EAGAIN);
+               ret = -EAGAIN;
+               goto err_unmap;
        }
        T("slram: Registered device %s from %luKiB to %luKiB\n", name,
                        (start / 1024), ((start + length) / 1024));
@@ -194,6 +194,16 @@ static int register_device(char *name, unsigned long start, unsigned long length
                        ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start,
                        ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end);
        return(0);
+
+err_unmap:
+       memunmap(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start);
+err_free_priv:
+       kfree((*curmtd)->mtdinfo->priv);
+err_free_list:
+       kfree((*curmtd)->mtdinfo);
+       kfree(*curmtd);
+       *curmtd = NULL;
+       return ret;
 }
 
 static void unregister_devices(void)