diff options
author | Taylor Blau <me@ttaylorr.com> | 2023-05-01 18:54:03 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2023-05-01 19:27:02 +0300 |
commit | 64f1e658e935bea6c9afdc4fa8be1d3ad6740355 (patch) | |
tree | f93db9257c69947b0320e7acb48a2c416444868a /contrib | |
parent | de2fb99006575d55f878f9a4d02726cb598c361d (diff) |
contrib/credential: avoid fixed-size buffer in libsecret
The libsecret credential helper reads the newline-delimited
protocol stream one line at a time by repeatedly calling fgets() into a
fixed-size buffer, and is thus affected by the vulnerability described
in the previous commit.
To mitigate this attack, avoid using a fixed-size buffer, and instead
rely on getline() to allocate a buffer as large as necessary to fit the
entire content of the line, preventing any protocol injection.
In most parts of Git we don't assume that every platform has getline().
But libsecret is primarily used on Linux, where we do already assume it
(using a knob in config.mak.uname). POSIX also added getline() in 2008,
so we'd expect other recent Unix-like operating systems to have it
(e.g., FreeBSD also does).
Note that the buffer was already allocated on the heap in this case, but
we'll swap `g_free()` for `free()`, since it will now be allocated by
the system `getline()`, rather than glib's `g_malloc()`.
Tested-by: Jeff King <peff@peff.net>
Co-authored-by: Jeff King <peff@peff.net>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Taylor Blau <me@ttaylorr.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/credential/libsecret/git-credential-libsecret.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/contrib/credential/libsecret/git-credential-libsecret.c b/contrib/credential/libsecret/git-credential-libsecret.c index 2c5d76d789..ef681f29d5 100644 --- a/contrib/credential/libsecret/git-credential-libsecret.c +++ b/contrib/credential/libsecret/git-credential-libsecret.c @@ -244,17 +244,16 @@ static void credential_clear(struct credential *c) static int credential_read(struct credential *c) { - char *buf; - size_t line_len; + char *buf = NULL; + size_t alloc; + ssize_t line_len; char *key; char *value; - key = buf = g_malloc(1024); + while ((line_len = getline(&buf, &alloc, stdin)) > 0) { + key = buf; - while (fgets(buf, 1024, stdin)) { - line_len = strlen(buf); - - if (line_len && buf[line_len-1] == '\n') + if (buf[line_len-1] == '\n') buf[--line_len] = '\0'; if (!line_len) @@ -298,7 +297,7 @@ static int credential_read(struct credential *c) */ } - g_free(buf); + free(buf); return 0; } |