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 <[email protected]>
---
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