git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [patch] credential-osxkeychain: Clear username_buffer before getting the converted C string.

From
Jeff King <peff@peff.net>
Date
Jul 31, 2024, 07:42 UTC
Message-ID
<20240731074228.GC595974@coredump.intra.peff.net>
In-Reply-To
<CAEcKSiyo3dyNpGkE_FWE-Y710RV0H3EytM2psC=+by=4wP5qpg@mail.gmail.com>
On Wed, Jul 31, 2024 at 11:41:23AM +0800, Hong Jiang wrote:
Show 14 quoted lines
> So it looks like that git_credential_out has invalid UTF-8 byte
> sequence. I print it after the system_command "git":
> 
> password=gho_SHADOWED
> username=jdp1024��`
> F�
> capability[]=state
> state[]=osxkeychain:seen=1
> 
> and
> 
> echo "protocol=https\nhost=github.com\n" | git credential-osxkeychain get
> 
> reproduced the problem.

Hmm. That does look like it could be uninitialized memory (assuming you don't have those garbage characters in the keychain storage).

> So I made the patch, which zeros the username_buf before retrieving
> the converted C string.

If that helps, then that implies that the string we are getting is not NUL-terminated. But...

Show 13 quoted lines
> diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
> b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
> index 6ce22a28ed..89cd575bd5 100644
> --- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
> +++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
> @@ -137,6 +137,7 @@ static void find_username_in_item(CFDictionaryRef item)
>   buffer_len = CFStringGetMaximumSizeForEncoding(
>   CFStringGetLength(account_ref), ENCODING) + 1;
>   username_buf = xmalloc(buffer_len);
> + memset(username_buf, 0, buffer_len);
>   if (CFStringGetCString(account_ref,
>   username_buf,
>   buffer_len,

...we are getting it by calling CFStringGetCString(). I don't know anything about the OS API here, and I don't have a system to test on. But according to the documentation at:

  https://developer.apple.com/documentation/corefoundation/1542721-cfstringgetcstring
it should return a NUL-terminated string.

Hrm. Just looking at the code, here's a wild hypothesis: the problem could be not that the buffer is not NUL-terminated, but that after the NUL it contains junk, and we print that junk. That is, the code looks like this:

          /* If we can't get a CString pointer then
           * we need to allocate our own buffer */
          buffer_len = CFStringGetMaximumSizeForEncoding(
                          CFStringGetLength(account_ref), ENCODING) + 1;
          username_buf = xmalloc(buffer_len);
          if (CFStringGetCString(account_ref,
                                  username_buf,
                                  buffer_len,
                                  ENCODING)) {
                  write_item("username", username_buf, buffer_len - 1);
          }

So we asked the system for the _maximum_ size that the string could be (and added one for the NUL). Then we got the string, and we printed out the _whole_ buffer, not just the string up to the NUL. And your fix "works" because NULs end up getting ignored on the read side (or at least cause ruby not to complain about bogus utf8).

If that hypothesis is true, then the fix is more like:
diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
index 6ce22a28ed..1c8310d7fe 100644
--- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
+++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
@@ -141,7 +141,7 @@ static void find_username_in_item(CFDictionaryRef item)
 				username_buf,
 				buffer_len,
 				ENCODING)) {
-		write_item("username", username_buf, buffer_len - 1);
+		write_item("username", username_buf, strlen(username_buf));
 	}
 	free(username_buf);
 }

But somebody with a functioning macOS system would need to check whether
any of what I just said is true. This code comes from 9abe31f5f1
(osxkeychain: replace deprecated SecKeychain API, 2024-02-17). Adding
the author to the CC.

-Peff
Previous: Hong JiangNext: Bo Anderson
Message 2 of 7 in “credential-osxkeychain: Clear username_buffer before getting the converted C string.”
  1. credential-osxkeychain: Clear username_buffer before getting the converted C string.Hong Jiang, Jul 31, 2024
  2. Jeff KingJul 31, 2024
  3. Bo AndersonJul 31, 2024
  4. credential/osxkeychain: respect NUL terminator in usernameJeff King, Aug 1, 2024
  5. Hong JiangAug 1, 2024
  6. Jeff KingAug 1, 2024
  7. Junio C HamanoAug 1, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.