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

Re: [PATCH 2/3] Guard memory overwriting in resolve_ref's static buffer

From
Jonathan Nieder <jrnieder@gmail.com>
Date
Dec 10, 2011, 21:10 UTC
Message-ID
<20111210211040.GB24817@elie.hsd1.il.comcast.net>
In-Reply-To
<1323521631-24320-2-git-send-email-pclouds@gmail.com>
Nguyễn Thái Ngọc Duy wrote:
Show 8 quoted lines
> Michael Haggerty
> has an idea [1] that, instead of passing the same static buffer to
> caller every time the function is called, we free the old buffer and
> allocate the new one. This way access to the old (now invalid) buffer
> may be caught.
>
> This patch applies the same principle for resolve_ref() with a
> few modifications:
[...]
>  - Rely on mmap/mprotect to catch illegal access. We need valgrind or
>    some other memory tracking tool to reliably catch this in Michael's
>    approach.

I wonder if the lower-tech approach would be so bad in practice. On systems using glibc, if MALLOC_PERTURB_ is set, then the value will always be clobbered on free(). It would be possible to do the same explicitly in resolve_ref() for platforms without such a feature.

>  - Because mprotect is used instead of munmap, we definitely leak
>    memory. Hopefully callers will not put resolve_ref() in a
>    loop that runs 1 million times.

Have you measured the performance impact when GIT_DEBUG_MEMCHECK is not set? (I don't expect major problems, but sometimes code surprises me.)

[...]
> Also introduce a new target, "make memcheck", that runs tests with this
> flag on.
Neat.  Did it catch any bugs?
Show 8 quoted lines
> --- a/cache.h
> +++ b/cache.h
> @@ -865,7 +865,8 @@ extern int read_ref(const char *filename, unsigned char *sha1);
>   *
>   * errno is sometimes set on errors, but not always.
>   */
> -extern const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag);
> +#define resolve_ref(ref, sha1, reading, flag) resolve_ref_real(ref, sha1, reading, flag, __FUNCTION__, __LINE__)

__FUNCTION__ is nonstandard, though it's probably supported pretty widely and we can do

	#ifndef __FUNCTION__
	#define __FUNCTION__ something-else
	#endif

in git-compat-util.h when we discover a platform that doesn't support it if needed. __func__ was introduced in C99. __LINE__ and __FILE__ should work everywhere.

[...]
Show 12 quoted lines
> --- /dev/null
> +++ b/t/t0071-memcheck.sh
> @@ -0,0 +1,12 @@
> +#!/bin/sh
> +
> +test_description='test that GIT_DEBUG_MEMCHECK works correctly'
> +. ./test-lib.sh
> +
> +test_expect_success 'test-resolve-ref must crash' '
> +	GIT_DEBUG_MEMCHECK=1 test-resolve-ref
> +	exit_code=$? &&
> +	test $exit_code -eq 139
Micronit: something like
	(
		GIT_DEBUG_MEMCHECK=1 &&
		export GIT_DEBUG_MEMCHECK &&
		test_expect_code 139 test-resolve-ref
	)
would fit better in an &&-list.
Show 20 quoted lines
> --- a/wrapper.c
> +++ b/wrapper.c
> @@ -60,6 +60,28 @@ void *xmallocz(size_t size)
>  	return ret;
>  }
>  
> +void *xmalloc_mmap(size_t size, const char *file, int line)
> +{
> +	int *ret;
> +	size += sizeof(int*) * 3;
> +	ret = mmap(NULL, size, PROT_READ | PROT_WRITE,
> +		   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
> +	if (ret == (int*)-1)
> +		die_errno("unable to mmap %lu bytes anonymously",
> +			  (unsigned long)size);
> +
> +	ret[0] = (int)file;
> +	ret[1] = line;
> +	ret[2] = size;
> +	return ret + 3;
Would this work on 64-bit platforms?

How does one retrieve the line and file number? I guess one is expected to retrieve them from the core dump, but a few words of advice in Documentation/technical would be helpful.

Previous: Nguyễn Thái Ngọc DuyNext: Nguyen Thai Ngoc Duy
Message 3 of 10 in “Convert resolve_ref+xstrdup to new resolve_refdup function”
  1. 1/3 Convert resolve_ref+xstrdup to new resolve_refdup functionNguyễn Thái Ngọc Duy, Dec 10, 2011
  2. 2/3 Guard memory overwriting in resolve_ref's static bufferNguyễn Thái Ngọc Duy, Dec 10, 2011
  3. Jonathan NiederDec 10, 2011
  4. Nguyen Thai Ngoc DuyDec 11, 2011
  5. 3/3 Rename resolve_ref() to resolve_ref_unsafe()Nguyễn Thái Ngọc Duy, Dec 10, 2011
  6. Jonathan NiederDec 10, 2011
  7. Nguyen Thai Ngoc DuyDec 11, 2011
  8. Jonathan NiederDec 10, 2011
  9. Nguyen Thai Ngoc DuyDec 10, 2011
  10. Junio C HamanoDec 12, 2011

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.