From: Igor Opaniuk Date: Sun, 12 Jul 2026 08:50:21 +0000 (+0200) Subject: avb: free mmc_part allocated by get_partition() X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f9c750ea306877432a525de1ebd9740ec815e5da;p=thirdparty%2Fu-boot.git avb: free mmc_part allocated by get_partition() get_partition() returns a malloc()'d struct mmc_part and only frees it on its own internal error path. None of its callers - mmc_byte_io(), get_unique_guid_for_partition() and get_size_of_partition() - free the returned pointer, so every partition access leaks one struct mmc_part. A single "avb verify" issues many such accesses (footer, vbmeta and the hashed image chunks), so the leak accumulates quickly. Free the descriptor in all three callers. mmc_byte_io() is reworked to use a single exit path so the partition is released on every return. Fixes: 3af30e4443aa ("avb2.0: implement AVB ops") Signed-off-by: Igor Opaniuk Reviewed-by: Mattijs Korpershoek Link: https://patch.msgid.link/20260712-avb-fix-memory-leaks-v1-2-51d6d5a42631@gmail.com Signed-off-by: Mattijs Korpershoek --- diff --git a/common/avb_verify.c b/common/avb_verify.c index 29a3272579c..76c523fd0ba 100644 --- a/common/avb_verify.c +++ b/common/avb_verify.c @@ -452,6 +452,7 @@ static AvbIOResult mmc_byte_io(AvbOps *ops, u64 start_offset, start_sector, sectors, residue; u8 *tmp_buf; size_t io_cnt = 0; + AvbIOResult io_ret = AVB_IO_RESULT_OK; if (!partition || !buffer || io_type > IO_WRITE) return AVB_IO_RESULT_ERROR_IO; @@ -460,8 +461,10 @@ static AvbIOResult mmc_byte_io(AvbOps *ops, if (!part) return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; - if (!part->info.blksz) - return AVB_IO_RESULT_ERROR_IO; + if (!part->info.blksz) { + io_ret = AVB_IO_RESULT_ERROR_IO; + goto out; + } start_offset = calc_offset(part, offset); while (num_bytes) { @@ -489,7 +492,8 @@ static AvbIOResult mmc_byte_io(AvbOps *ops, if (ret != 1) { printf("%s: read error (%ld, %lld)\n", __func__, ret, start_sector); - return AVB_IO_RESULT_ERROR_IO; + io_ret = AVB_IO_RESULT_ERROR_IO; + goto out; } /* * if this is not aligned at sector start, @@ -506,7 +510,8 @@ static AvbIOResult mmc_byte_io(AvbOps *ops, if (ret != 1) { printf("%s: read error (%ld, %lld)\n", __func__, ret, start_sector); - return AVB_IO_RESULT_ERROR_IO; + io_ret = AVB_IO_RESULT_ERROR_IO; + goto out; } memcpy((void *)tmp_buf + start_offset % part->info.blksz, @@ -517,7 +522,8 @@ static AvbIOResult mmc_byte_io(AvbOps *ops, if (ret != 1) { printf("%s: write error (%ld, %lld)\n", __func__, ret, start_sector); - return AVB_IO_RESULT_ERROR_IO; + io_ret = AVB_IO_RESULT_ERROR_IO; + goto out; } } @@ -543,7 +549,8 @@ static AvbIOResult mmc_byte_io(AvbOps *ops, if (!ret) { printf("%s: sector read error\n", __func__); - return AVB_IO_RESULT_ERROR_IO; + io_ret = AVB_IO_RESULT_ERROR_IO; + goto out; } io_cnt += ret * part->info.blksz; @@ -557,7 +564,9 @@ static AvbIOResult mmc_byte_io(AvbOps *ops, if (io_type == IO_READ && out_num_read) *out_num_read = io_cnt; - return AVB_IO_RESULT_OK; +out: + free(part); + return io_ret; } /** @@ -867,12 +876,15 @@ static AvbIOResult get_unique_guid_for_partition(AvbOps *ops, return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; uuid_size = sizeof(part->info.uuid); - if (uuid_size > guid_buf_size) + if (uuid_size > guid_buf_size) { + free(part); return AVB_IO_RESULT_ERROR_IO; + } memcpy(guid_buf, part->info.uuid, uuid_size); guid_buf[uuid_size - 1] = 0; + free(part); return AVB_IO_RESULT_OK; } @@ -903,6 +915,7 @@ static AvbIOResult get_size_of_partition(AvbOps *ops, return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION; *out_size_num_bytes = part->info.blksz * part->info.size; + free(part); return AVB_IO_RESULT_OK; }