michal-grzedzicki / rpms / rpm

Forked from rpms/rpm 4 months ago
Clone
Blob Blame History Raw
From 937f9bc67b905851c78719d8397926eaa97b174a Mon Sep 17 00:00:00 2001
From: Richard Phibel <richardphibel@meta.com>
Date: Mon, 22 May 2023 05:16:51 +0200
Subject: [PATCH] Fix stack overflow

Creation of array struct digestoffset offsets[rpmfiFC(fi)] caused a
stack overflow because the total size is greater than 8M which is the
stack size limit on Linux. To fix the issue, the array is allocated on
the heap.

I used AddressSanitizer to find the root cause of the issue. It found a
number of memory leaks so I fixed them as well.
---
 rpm2extents.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/rpm2extents.c b/rpm2extents.c
index c2a373914..0ee8666fa 100644
--- a/rpm2extents.c
+++ b/rpm2extents.c
@@ -226,6 +226,7 @@ exit:
     if(msg) {
 	free(msg);
     }
+    rpmtsFree(ts);
     return rc;
 }
 
@@ -243,6 +244,7 @@ static void sanitizeSignatureHeader(Header * sigh)
 	*sigh = headerLink(nh);
 	headerFree(nh);
     }
+    rpmtdFreeData(&td);
 }
 
 static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
@@ -281,6 +283,8 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
     rpmfiles files = NULL;
     rpmfi fi = NULL;
     char *msg = NULL;
+    struct digestoffset *offsets = NULL;
+    digestSet ds = NULL;
 
     fdo = fdDup(STDOUT_FILENO);
 
@@ -357,10 +361,8 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
 	 * now?)
 	 */
 	diglen = (uint32_t) rpmDigestLength(rpmfiDigestAlgo(fi));
-	digestSet ds =
-	    digestSetCreate(rpmfiFC(fi), digestSetHash, digestSetCmp,
-			    NULL);
-	struct digestoffset offsets[rpmfiFC(fi)];
+	ds = digestSetCreate(rpmfiFC(fi), digestSetHash, digestSetCmp, NULL);
+	offsets = xcalloc(rpmfiFC(fi), sizeof(*offsets));
 	pos = RPMLEAD_SIZE + headerSizeof(sigh, HEADER_MAGIC_YES);
 
 	/* main headers are aligned to 8 byte boundry */
@@ -494,6 +496,10 @@ static rpmRC process_package(FD_t fdi, FD_t digestori, FD_t validationi)
     rpmfilesFree(files);
     rpmfiFree(fi);
     headerFree(h);
+    headerFree(sigh);
+    free(offsets);
+    Fclose(fdo);
+    digestSetFree(ds);
     return rc;
 }
 
@@ -693,6 +699,7 @@ int main(int argc, char *argv[]) {
 
     FD_t fdi = fdDup(STDIN_FILENO);
     rc = teeRpm(fdi, algos, nb_algos);
+    Fclose(fdi);
     if (rc != RPMRC_OK) {
 	/* translate rpmRC into generic failure return code. */
 	return EXIT_FAILURE;
-- 
2.40.1