diff options
author | Hou Tao | 2019-11-30 17:48:25 +0800 |
---|---|---|
committer | Richard Weinberger | 2020-01-16 23:35:59 +0100 |
commit | fc55dacf7fea793e70c9c75a1acff47a4fb02017 (patch) | |
tree | 322ea53989f168fdce2826455193d77364dadf43 /drivers/mtd/ubi/build.c | |
parent | 9d6c4742f96cc0380a3f2854d62c667b87736d71 (diff) |
ubi: Free the normal volumes in error paths of ubi_attach_mtd_dev()
The allocated normal volumes saved in ubi->volumes are not freed
in the error paths in ubi_attach_mtd_dev() and its callees (e.g.
ubi_attach() and ubi_read_volume_table()).
These normal volumes should be freed through kill_volumes() and
vol_release(), but ubi_attach_mtd_dev() may fail before
calling uif_init(), and there will be memory leaks.
So adding a new helper ubi_free_all_volumes() to free the normal
and the internal volumes. And in order to prevent double-free
of volume, reset ubi->volumes[i] to NULL after freeing.
Signed-off-by: Hou Tao <houtao1@huawei.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
Diffstat (limited to 'drivers/mtd/ubi/build.c')
-rw-r--r-- | drivers/mtd/ubi/build.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index d636bbe214cb..25fb72b2efa0 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -503,21 +503,42 @@ static void uif_close(struct ubi_device *ubi) } /** - * ubi_free_internal_volumes - free internal volumes. + * ubi_free_volumes_from - free volumes from specific index. * @ubi: UBI device description object + * @from: the start index used for volume free. */ -void ubi_free_internal_volumes(struct ubi_device *ubi) +static void ubi_free_volumes_from(struct ubi_device *ubi, int from) { int i; - for (i = ubi->vtbl_slots; - i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { + for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { + if (!ubi->volumes[i]) + continue; ubi_eba_replace_table(ubi->volumes[i], NULL); ubi_fastmap_destroy_checkmap(ubi->volumes[i]); kfree(ubi->volumes[i]); + ubi->volumes[i] = NULL; } } +/** + * ubi_free_all_volumes - free all volumes. + * @ubi: UBI device description object + */ +void ubi_free_all_volumes(struct ubi_device *ubi) +{ + ubi_free_volumes_from(ubi, 0); +} + +/** + * ubi_free_internal_volumes - free internal volumes. + * @ubi: UBI device description object + */ +void ubi_free_internal_volumes(struct ubi_device *ubi) +{ + ubi_free_volumes_from(ubi, ubi->vtbl_slots); +} + static int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024) { int limit, device_pebs; @@ -1013,7 +1034,7 @@ out_uif: out_detach: ubi_devices[ubi_num] = NULL; ubi_wl_close(ubi); - ubi_free_internal_volumes(ubi); + ubi_free_all_volumes(ubi); vfree(ubi->vtbl); out_free: vfree(ubi->peb_buf); |