[PATCH 2/2] avb: free mmc_part allocated by get_partition()

Igor Opaniuk igor.opaniuk at gmail.com
Sun Jul 12 10:50:21 CEST 2026


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 <igor.opaniuk at gmail.com>
---
 common/avb_verify.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

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;
 }

-- 
2.53.0



More information about the U-Boot mailing list