| From 5d3805af279c93ef49a64701f35254676d709622 Mon Sep 17 00:00:00 2001 |
| From: Dan Carpenter <dan.carpenter@oracle.com> |
| Date: Mon, 13 Jan 2020 16:23:46 +0300 |
| Subject: ubi: Fix an error pointer dereference in error handling code |
| |
| From: Dan Carpenter <dan.carpenter@oracle.com> |
| |
| 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 | 21 ++++++++++++--------- |
| 1 file changed, 12 insertions(+), 9 deletions(-) |
| |
| --- a/drivers/mtd/ubi/fastmap.c |
| +++ b/drivers/mtd/ubi/fastmap.c |
| @@ -1146,7 +1146,7 @@ static int ubi_write_fastmap(struct 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); |
| @@ -1160,7 +1160,7 @@ static int ubi_write_fastmap(struct 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); |
| @@ -1169,7 +1169,7 @@ static int ubi_write_fastmap(struct 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); |
| @@ -1337,7 +1337,7 @@ static int ubi_write_fastmap(struct 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++) { |
| @@ -1359,7 +1359,7 @@ static int ubi_write_fastmap(struct 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; |
| } |
| } |
| |
| @@ -1369,7 +1369,7 @@ static int ubi_write_fastmap(struct 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; |
| } |
| } |
| |
| @@ -1379,10 +1379,13 @@ static int ubi_write_fastmap(struct 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; |
| } |