ubi: Fix an error pointer dereference in error handling code
authorDan Carpenter <dan.carpenter@oracle.com>
Mon, 13 Jan 2020 13:23:46 +0000 (16:23 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 14 Feb 2020 21:31:06 +0000 (16:31 -0500)
commit 5d3805af279c93ef49a64701f35254676d709622 upstream.

If "seen_pebs = init_seen(ubi);" fails then "seen_pebs" is an error pointer
and we try to kfree() it which results in an Oops.

This patch re-arranges the error handling so now it only frees things
which have been allocated successfully.

Fixes: daef3dd1f0ae ("UBI: Fastmap: Add self check to detect absent PEBs")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/mtd/ubi/fastmap.c

index 11dfbdf..e7b177c 100644 (file)
@@ -1127,7 +1127,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
        struct rb_node *tmp_rb;
        int ret, i, j, free_peb_count, used_peb_count, vol_count;
        int scrub_peb_count, erase_peb_count;
-       unsigned long *seen_pebs = NULL;
+       unsigned long *seen_pebs;
 
        fm_raw = ubi->fm_buf;
        memset(ubi->fm_buf, 0, ubi->fm_size);
@@ -1141,7 +1141,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
        dvbuf = new_fm_vbuf(ubi, UBI_FM_DATA_VOLUME_ID);
        if (!dvbuf) {
                ret = -ENOMEM;
-               goto out_kfree;
+               goto out_free_avbuf;
        }
 
        avhdr = ubi_get_vid_hdr(avbuf);
@@ -1150,7 +1150,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
        seen_pebs = init_seen(ubi);
        if (IS_ERR(seen_pebs)) {
                ret = PTR_ERR(seen_pebs);
-               goto out_kfree;
+               goto out_free_dvbuf;
        }
 
        spin_lock(&ubi->volumes_lock);
@@ -1318,7 +1318,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
        ret = ubi_io_write_vid_hdr(ubi, new_fm->e[0]->pnum, avbuf);
        if (ret) {
                ubi_err(ubi, "unable to write vid_hdr to fastmap SB!");
-               goto out_kfree;
+               goto out_free_seen;
        }
 
        for (i = 0; i < new_fm->used_blocks; i++) {
@@ -1340,7 +1340,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
                if (ret) {
                        ubi_err(ubi, "unable to write vid_hdr to PEB %i!",
                                new_fm->e[i]->pnum);
-                       goto out_kfree;
+                       goto out_free_seen;
                }
        }
 
@@ -1350,7 +1350,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
                if (ret) {
                        ubi_err(ubi, "unable to write fastmap to PEB %i!",
                                new_fm->e[i]->pnum);
-                       goto out_kfree;
+                       goto out_free_seen;
                }
        }
 
@@ -1360,10 +1360,13 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
        ret = self_check_seen(ubi, seen_pebs);
        dbg_bld("fastmap written!");
 
-out_kfree:
-       ubi_free_vid_buf(avbuf);
-       ubi_free_vid_buf(dvbuf);
+out_free_seen:
        free_seen(seen_pebs);
+out_free_dvbuf:
+       ubi_free_vid_buf(dvbuf);
+out_free_avbuf:
+       ubi_free_vid_buf(avbuf);
+
 out:
        return ret;
 }