"GOT", but the "O" is a cute, smiling pufferfish. Index | Thread | Search

From:
Mark Jamsek <mark@jamsek.com>
Subject:
Re: ID metadata leak
To:
Stefan Sperling <stsp@stsp.name>
Cc:
Kyle Ackerman <kackerman0102@gmail.com>, gameoftrees@openbsd.org
Date:
Wed, 13 Nov 2024 03:00:42 +1100

Download raw body.

Thread
Stefan Sperling <stsp@stsp.name> wrote:
> On Fri, Nov 08, 2024 at 10:35:34AM -0600, Kyle Ackerman wrote:
> > ping
> 
> Committed now, thanks!


I think there's still a leak in got_send_pack() when the reference is a
duplicate and thus not inserted into the `have_refs` list in the call to
insert_sendable_ref(). Specifically, the `s` argument passed as the
target_refname parameter, which points to an object obtained by either
strdup(3) or asprintf(3), is leaked in the duplicate case. It is
unconditionally set to NULL on each iteration with the assumption it
will be released in the subsequent got_pathlist_free() call.

Similarly, got_fetch_pack() still leaks `refname`, which is also the
argument passed as the path parameter to got_pathlist_insert(). Like
`id`, it is allocated in got_privsep_recv_fetch_progress(), but it is
not released in the duplicate case like we now do with `id`. Relatedly,
whenever the got_pathlist_insert() call in got_fetch_pack() fails, the
path entry is not inserted into the refs list and we jump straight to
done:, so both refname and id are leaked.

The first of the below diffs plugs these leaks. The second is a small,
nearby whitespace fix spotted while investigating this.


-----------------------------------------------
commit ecd282adab9a71f73be6b57b17ea572b72179c17
from: Mark Jamsek <mark@jamsek.dev>
date: Tue Nov 12 15:38:29 2024 UTC
 
 plug memory leaks in 'got fetch' and 'got send'
 
 In addition to the previous plugged leaks here, free what would be
 the path entry's path member, which is leaked when attempting to
 add a duplicate. And in the fetch case, free refname and id when
 got_pathlist_insert() fails.
 
 M  include/got_error.h  |   1+  0-
 M  lib/error.c          |   1+  0-
 M  lib/fetch.c          |   5+  3-
 M  lib/send.c           |  16+  5-

4 files changed, 23 insertions(+), 8 deletions(-)

diff d3e5e1573bd462d20d38aa0aa6535fcea6c0a948 ecd282adab9a71f73be6b57b17ea572b72179c17
commit - d3e5e1573bd462d20d38aa0aa6535fcea6c0a948
commit + ecd282adab9a71f73be6b57b17ea572b72179c17
blob - cc02089bfcb70faf1775da8b8a38eb7bfd903018
blob + 4181bc79115b549c541be0a74f00f51030a6135d
--- include/got_error.h
+++ include/got_error.h
@@ -188,6 +188,7 @@
 #define GOT_ERR_BUNDLE_FORMAT 171
 #define GOT_ERR_BAD_KEYWORD	172
 #define GOT_ERR_UNKNOWN_CAPA	173
+#define GOT_ERR_REF_DUP_ENTRY	174
 
 struct got_error {
         int code;
blob - 8872bef06f42c654a7f90d728cc11aadb624cf2e
blob + b75dde1c3fc3d4e86f60fe5fa47a7f09526358bf
--- lib/error.c
+++ lib/error.c
@@ -239,6 +239,7 @@ static const struct got_error got_errors[] = {
 	{ GOT_ERR_BUNDLE_FORMAT, "unknown git bundle version" },
 	{ GOT_ERR_BAD_KEYWORD, "invalid commit keyword" },
 	{ GOT_ERR_UNKNOWN_CAPA, "unknown capability" },
+	{ GOT_ERR_REF_DUP_ENTRY, "duplicate reference entry" },
 };
 
 static struct got_custom_error {
blob - f03b63655d11f0912e5c2dd4b182296979de8e36
blob + 4d56359502a5b5c1e7fc70c62f2355e4e13e7960
--- lib/fetch.c
+++ lib/fetch.c
@@ -314,10 +314,12 @@ got_fetch_pack(struct got_object_id **pack_hash, struc
 			packfile_size_cur = 0;
 		if (!done && refname && id) {
 			err = got_pathlist_insert(&pe, refs, refname, id);
-			if (err)
-				goto done;
-			if (pe == NULL)
+			if (err || pe == NULL) {
 				free(id);
+				free(refname);
+				if (err != NULL)
+					goto done;
+			}
 		} else if (!done && server_progress) {
 			char *p;
 			/*
blob - 8ec7b9fb1ba48a9fa452a728bb1787df461ef284
blob + 65890785ca1e642d75f9495fc8450e57bdc2806a
--- lib/send.c
+++ lib/send.c
@@ -202,10 +202,13 @@ insert_sendable_ref(struct got_pathlist_head *refs, co
 	}
 
 	err = got_pathlist_insert(&new, refs, target_refname, id);
+	if (new == NULL && err == NULL)
+		err = got_error(GOT_ERR_REF_DUP_ENTRY);
+
 done:
 	if (ref)
 		got_ref_close(ref);
-	if (err || new == NULL /* duplicate */)
+	if (err)
 		free(id);
 	return err;
 }
@@ -388,8 +391,12 @@ got_send_pack(const char *remote_name, struct got_path
 			}
 		}
 		err = insert_sendable_ref(&have_refs, branchname, s, repo);
-		if (err)
-			goto done;
+		if (err) {
+			if (err->code != GOT_ERR_REF_DUP_ENTRY)
+				goto done;
+			err = NULL;
+			free(s);
+		}
 		s = NULL;
 	}
 
@@ -424,8 +431,12 @@ got_send_pack(const char *remote_name, struct got_path
 			}
 		}
 		err = insert_sendable_ref(&have_refs, s, s, repo);
-		if (err)
-			goto done;
+		if (err) {
+			if (err->code != GOT_ERR_REF_DUP_ENTRY)
+				goto done;
+			err = NULL;
+			free(s);
+		}
 		s = NULL;
 	}
 

-----------------------------------------------
commit e4716d841dc7bebea2ceb5cd9da6807682c8cec3 (main)
from: Mark Jamsek <mark@jamsek.dev>
date: Tue Nov 12 15:38:30 2024 UTC
 
 whitespace
 
 M  lib/send.c  |  1+  1-

1 file changed, 1 insertion(+), 1 deletion(-)

diff ecd282adab9a71f73be6b57b17ea572b72179c17 e4716d841dc7bebea2ceb5cd9da6807682c8cec3
commit - ecd282adab9a71f73be6b57b17ea572b72179c17
commit + e4716d841dc7bebea2ceb5cd9da6807682c8cec3
blob - 65890785ca1e642d75f9495fc8450e57bdc2806a
blob + 4fb5f3aad871abb2d8ad18e445fb9dff32c8c6b0
--- lib/send.c
+++ lib/send.c
@@ -196,7 +196,7 @@ insert_sendable_ref(struct got_pathlist_head *refs, co
 	case GOT_OBJ_TYPE_TAG:
 		break;
 	default:
-		err = got_error_fmt(GOT_ERR_OBJ_TYPE," cannot send %s",
+		err = got_error_fmt(GOT_ERR_OBJ_TYPE, "cannot send %s",
 		    refname);
 		goto done;
 	}


-- 
Mark Jamsek <https://bsdbox.org>
GPG: F2FF 13DE 6A06 C471 CA80  E6E2 2930 DC66 86EE CF68