Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Hou Tao and committed by
Richard Weinberger
fc55dacf 9d6c4742

+34 -18
+1 -1
drivers/mtd/ubi/attach.c
··· 1640 1640 out_wl: 1641 1641 ubi_wl_close(ubi); 1642 1642 out_vtbl: 1643 - ubi_free_internal_volumes(ubi); 1643 + ubi_free_all_volumes(ubi); 1644 1644 vfree(ubi->vtbl); 1645 1645 out_ai: 1646 1646 destroy_ai(ai);
+30 -9
drivers/mtd/ubi/build.c
··· 503 503 } 504 504 505 505 /** 506 + * ubi_free_volumes_from - free volumes from specific index. 507 + * @ubi: UBI device description object 508 + * @from: the start index used for volume free. 509 + */ 510 + static void ubi_free_volumes_from(struct ubi_device *ubi, int from) 511 + { 512 + int i; 513 + 514 + for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { 515 + if (!ubi->volumes[i]) 516 + continue; 517 + ubi_eba_replace_table(ubi->volumes[i], NULL); 518 + ubi_fastmap_destroy_checkmap(ubi->volumes[i]); 519 + kfree(ubi->volumes[i]); 520 + ubi->volumes[i] = NULL; 521 + } 522 + } 523 + 524 + /** 525 + * ubi_free_all_volumes - free all volumes. 526 + * @ubi: UBI device description object 527 + */ 528 + void ubi_free_all_volumes(struct ubi_device *ubi) 529 + { 530 + ubi_free_volumes_from(ubi, 0); 531 + } 532 + 533 + /** 506 534 * ubi_free_internal_volumes - free internal volumes. 507 535 * @ubi: UBI device description object 508 536 */ 509 537 void ubi_free_internal_volumes(struct ubi_device *ubi) 510 538 { 511 - int i; 512 - 513 - for (i = ubi->vtbl_slots; 514 - i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { 515 - ubi_eba_replace_table(ubi->volumes[i], NULL); 516 - ubi_fastmap_destroy_checkmap(ubi->volumes[i]); 517 - kfree(ubi->volumes[i]); 518 - } 539 + ubi_free_volumes_from(ubi, ubi->vtbl_slots); 519 540 } 520 541 521 542 static int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024) ··· 1034 1013 out_detach: 1035 1014 ubi_devices[ubi_num] = NULL; 1036 1015 ubi_wl_close(ubi); 1037 - ubi_free_internal_volumes(ubi); 1016 + ubi_free_all_volumes(ubi); 1038 1017 vfree(ubi->vtbl); 1039 1018 out_free: 1040 1019 vfree(ubi->peb_buf);
+1
drivers/mtd/ubi/ubi.h
··· 950 950 int ubi_notify_all(struct ubi_device *ubi, int ntype, 951 951 struct notifier_block *nb); 952 952 int ubi_enumerate_volumes(struct notifier_block *nb); 953 + void ubi_free_all_volumes(struct ubi_device *ubi); 953 954 void ubi_free_internal_volumes(struct ubi_device *ubi); 954 955 955 956 /* kapi.c */
+2 -8
drivers/mtd/ubi/vtbl.c
··· 782 782 */ 783 783 int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai) 784 784 { 785 - int i, err; 785 + int err; 786 786 struct ubi_ainf_volume *av; 787 787 788 788 empty_vtbl_record.crc = cpu_to_be32(0xf116c36b); ··· 851 851 852 852 out_free: 853 853 vfree(ubi->vtbl); 854 - for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { 855 - if (!ubi->volumes[i]) 856 - continue; 857 - ubi_fastmap_destroy_checkmap(ubi->volumes[i]); 858 - kfree(ubi->volumes[i]); 859 - ubi->volumes[i] = NULL; 860 - } 854 + ubi_free_all_volumes(ubi); 861 855 return err; 862 856 } 863 857