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

Reply via email to