Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-23 Thread Duy Nguyen
On Tue, Oct 22, 2013 at 2:02 AM, Johannes Sixt j...@kdbg.org wrote:
 (or maybe at higher level to skip checking out those paths).

 More like this, yeah.

The good thing is we do not stop checking out if one entry fails. But
due to the lack of worktree entries, one may accidentally remove files
in new commits. So setting CE_VALID on failed-to-checkout entries
might help. I'm not sure. But I won't pursue because Windows is not
really my itch.
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-21 Thread Johannes Sixt
Am 21.10.2013 03:31, schrieb Duy Nguyen:
 On Mon, Oct 21, 2013 at 12:57 AM, Antoine Pelisse apeli...@gmail.com wrote:
 My main motive was to not *stop* the process when a long path is met.
 Because somebody created a repository on Linux with a long file-name
 doesn't mean you should not be able to clone it *at all* on Windows.
 
 That should be handled at the Windows compatibility layer if Windows
 cannot handle long paths as Linux

Naah... PATH_MAX is a silly, arbitrary limit. The Git data model does
not forbid paths longer than PATH_MAX, be it 4096 or 260. A generic
solution is needed.

 (or maybe at higher level to skip
 checking out those paths).

More like this, yeah.

-- Hannes

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-21 Thread Erik Faye-Lund
On Mon, Oct 21, 2013 at 9:02 PM, Johannes Sixt j...@kdbg.org wrote:
 Am 21.10.2013 03:31, schrieb Duy Nguyen:
 On Mon, Oct 21, 2013 at 12:57 AM, Antoine Pelisse apeli...@gmail.com wrote:
 My main motive was to not *stop* the process when a long path is met.
 Because somebody created a repository on Linux with a long file-name
 doesn't mean you should not be able to clone it *at all* on Windows.

 That should be handled at the Windows compatibility layer if Windows
 cannot handle long paths as Linux

 Naah... PATH_MAX is a silly, arbitrary limit. The Git data model does
 not forbid paths longer than PATH_MAX, be it 4096 or 260. A generic
 solution is needed.

 (or maybe at higher level to skip
 checking out those paths).

 More like this, yeah.

I would argue that this is probably even a bug on Linux, only harder
(if not impossible) to trigger by accident as there's probably no
git-client that will generate such trees. But a malicious client
might.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-21 Thread Jeff King
On Mon, Oct 21, 2013 at 09:07:26PM +0200, Erik Faye-Lund wrote:

 I would argue that this is probably even a bug on Linux, only harder
 (if not impossible) to trigger by accident as there's probably no
 git-client that will generate such trees. But a malicious client
 might.

I've just been poking through the impacts of these overflows, for that
exact reason. I don't think any of them are easily triggerable by
somebody sending you a malicious tree (e.g., the `remove_subtree` one
only triggers when we have seen that tree in the filesystem, so it must
be limited to `PATH_MAX`). Some of them are triggerable if you use
particular options (e.g., the one in `match_order` is easy to trigger if
you use `diff -O`).

Still, they should all be fixed, even for Linux. I shouldn't have to
trace the provenance of the data back through 10 functions just to find
out a buffer overflow isn't easily exploitable. :)

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-21 Thread Jeff King
On Mon, Oct 21, 2013 at 03:14:39PM -0400, Jeff King wrote:

 On Mon, Oct 21, 2013 at 09:07:26PM +0200, Erik Faye-Lund wrote:
 
  I would argue that this is probably even a bug on Linux, only harder
  (if not impossible) to trigger by accident as there's probably no
  git-client that will generate such trees. But a malicious client
  might.
 
 I've just been poking through the impacts of these overflows, for that
 exact reason. I don't think any of them are easily triggerable by
 somebody sending you a malicious tree (e.g., the `remove_subtree` one
 only triggers when we have seen that tree in the filesystem, so it must
 be limited to `PATH_MAX`). Some of them are triggerable if you use
 particular options (e.g., the one in `match_order` is easy to trigger if
 you use `diff -O`).

Actually, I take that back. The one in checkout_entry is quite easy to
trigger if the victim checks out your tree. The rest are much harder,
though.

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-20 Thread Ondřej Bílka
On Sun, Oct 20, 2013 at 07:47:06AM +0200, Torsten Bögershausen wrote:
 (may be s/path is too big/path is too long/ ?)
 
 On 19.10.13 12:52, Antoine Pelisse wrote:
  Currently, most buffers created with PATH_MAX length, are not checked
  when being written, and can overflow if PATH_MAX is not big enough to
  hold the path.
  
  Fix that by using strlcpy() where strcpy() was used, and also run some
  extra checks when copy is done with memcpy().
  
  Reported-by: Wataru Noguchi wnoguchi.0...@gmail.com
  Signed-off-by: Antoine Pelisse apeli...@gmail.com
  ---
  diff --git a/abspath.c b/abspath.c
  index 64adbe2..0e60ba4 100644
  --- a/abspath.c
  +++ b/abspath.c
  @@ -216,11 +216,15 @@ const char *absolute_path(const char *path)
   const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
   {
  static char path[PATH_MAX];

Why do you need static there?
  +
  +   if (pfx_len  PATH_MAX)
 I think this should be 
 if (pfx_len  PATH_MAX-1) /* Keep 1 char for '\0'
  +   die(Too long prefix path: %s, pfx);
  +
   #ifndef GIT_WINDOWS_NATIVE
  if (!pfx_len || is_absolute_path(arg))
  return arg;
  memcpy(path, pfx, pfx_len);
  -   strcpy(path + pfx_len, arg);
  +   strlcpy(path + pfx_len, arg, PATH_MAX - pfx_len);
 
 I'm not sure how to handle overlong path in general, there are several ways:
 a) Silently overwrite memory (with help of memcpy() and/or strcpy()
 b) Silently shorten the path using strlcpy() instead of strcpy()
 c) Avoid the overwriting and call die().
 d) Prepare a longer buffer using xmalloc()
 
There is also
e) modify allocation to place write protected page after buffer end.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-20 Thread Torsten Bögershausen
On 20.10.13 08:05, Ondřej Bílka wrote:
 On Sun, Oct 20, 2013 at 07:47:06AM +0200, Torsten Bögershausen wrote:
 (may be s/path is too big/path is too long/ ?)

 On 19.10.13 12:52, Antoine Pelisse wrote:
 Currently, most buffers created with PATH_MAX length, are not checked
 when being written, and can overflow if PATH_MAX is not big enough to
 hold the path.

 Fix that by using strlcpy() where strcpy() was used, and also run some
 extra checks when copy is done with memcpy().

 Reported-by: Wataru Noguchi wnoguchi.0...@gmail.com
 Signed-off-by: Antoine Pelisse apeli...@gmail.com
 ---
 diff --git a/abspath.c b/abspath.c
 index 64adbe2..0e60ba4 100644
 --- a/abspath.c
 +++ b/abspath.c
 @@ -216,11 +216,15 @@ const char *absolute_path(const char *path)
  const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
  {
 static char path[PATH_MAX];
 
 Why do you need static there?
Good point.
get_pathname() from path.c may be better.

 +
 +   if (pfx_len  PATH_MAX)
 I think this should be 
 if (pfx_len  PATH_MAX-1) /* Keep 1 char for '\0'
 +   die(Too long prefix path: %s, pfx);
 +
  #ifndef GIT_WINDOWS_NATIVE
 if (!pfx_len || is_absolute_path(arg))
 return arg;
 memcpy(path, pfx, pfx_len);
 -   strcpy(path + pfx_len, arg);
 +   strlcpy(path + pfx_len, arg, PATH_MAX - pfx_len);

 I'm not sure how to handle overlong path in general, there are several ways:
 a) Silently overwrite memory (with help of memcpy() and/or strcpy()
 b) Silently shorten the path using strlcpy() instead of strcpy()
 c) Avoid the overwriting and call die().
 d) Prepare a longer buffer using xmalloc()

 There is also
 e) modify allocation to place write protected page after buffer end.

Yes, I think this is what electric fence, DUMA or valgrind do:

http://sourceforge.jp/projects/freshmeat_efence/
http://duma.sourceforge.net/
http://valgrind.sourceforge.net/

Theses are very good tools for developers, finding memory corruption
(or other bugs like using uninitialized memory).

One of the motivation I asked for test cases is that a git developer can
run these test cases under valgrind and can verify that we are never out of 
range.

For an end user a git crash caused by trying to write to a write protected 
page
is better than silently corrupting memory.

And a range check, followed by die(), is even easier to debug.
For an end user.
/Torsten

















--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-20 Thread Ondřej Bílka
On Sun, Oct 20, 2013 at 08:27:13AM +0200, Torsten Bögershausen wrote:
 Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on
   popelka.ms.mff.cuni.cz
 Status: O
 Content-Length: 2690
 Lines: 89
 
 On 20.10.13 08:05, Ondřej Bílka wrote:
  On Sun, Oct 20, 2013 at 07:47:06AM +0200, Torsten Bögershausen wrote:
  (may be s/path is too big/path is too long/ ?)
 
  On 19.10.13 12:52, Antoine Pelisse wrote:
  Currently, most buffers created with PATH_MAX length, are not checked
  when being written, and can overflow if PATH_MAX is not big enough to
  hold the path.
 
  Fix that by using strlcpy() where strcpy() was used, and also run some
  extra checks when copy is done with memcpy().
 
  Reported-by: Wataru Noguchi wnoguchi.0...@gmail.com
  Signed-off-by: Antoine Pelisse apeli...@gmail.com
  ---
  diff --git a/abspath.c b/abspath.c
  index 64adbe2..0e60ba4 100644
  --- a/abspath.c
  +++ b/abspath.c
  @@ -216,11 +216,15 @@ const char *absolute_path(const char *path)
   const char *prefix_filename(const char *pfx, int pfx_len, const char 
  *arg)
   {
static char path[PATH_MAX];
  
  Why do you need static there?
 Good point.
 get_pathname() from path.c may be better.
 
  +
  + if (pfx_len  PATH_MAX)
  I think this should be 
  if (pfx_len  PATH_MAX-1) /* Keep 1 char for '\0'
  + die(Too long prefix path: %s, pfx);
  +
   #ifndef GIT_WINDOWS_NATIVE
if (!pfx_len || is_absolute_path(arg))
return arg;
memcpy(path, pfx, pfx_len);
  - strcpy(path + pfx_len, arg);
  + strlcpy(path + pfx_len, arg, PATH_MAX - pfx_len);
 
  I'm not sure how to handle overlong path in general, there are several 
  ways:
  a) Silently overwrite memory (with help of memcpy() and/or strcpy()
  b) Silently shorten the path using strlcpy() instead of strcpy()
  c) Avoid the overwriting and call die().
  d) Prepare a longer buffer using xmalloc()
 
  There is also
  e) modify allocation to place write protected page after buffer end.
 
 Yes, I think this is what electric fence, DUMA or valgrind do:
 
You need to be selective which buffers are important.

 http://sourceforge.jp/projects/freshmeat_efence/
 http://duma.sourceforge.net/

These are toys, this comes with fact that they need a 8kb of space for
each 8byte malloc. Just run a git diff and differences are huge.

$ /usr/bin/time git diff HEAD^  x
0.06user 0.01system 0:00.07elapsed 97%CPU (0avgtext+0avgdata
19172maxresident)k
0inputs+8outputs (0major+5591minor)pagefaults 0swaps
$ LD_PRELOAD=libefence.so /usr/bin/time git diff HEAD^  x

  Electric Fence 2.2 Copyright (C) 1987-1999 Bruce Perens
br...@perens.com
3.49user 0.94system 0:04.45elapsed 99%CPU (0avgtext+0avgdata
91920maxresident)k
0inputs+8outputs (0major+118069minor)pagefaults 0swaps

 http://valgrind.sourceforge.net/
 
 Theses are very good tools for developers, finding memory corruption
 (or other bugs like using uninitialized memory).
 
 One of the motivation I asked for test cases is that a git developer can
 run these test cases under valgrind and can verify that we are never out of 
 range.
 
 For an end user a git crash caused by trying to write to a write protected 
 page
 is better than silently corrupting memory.
 
 And a range check, followed by die(), is even easier to debug.
 For an end user.
 /Torsten
 
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-20 Thread Duy Nguyen
On Sun, Oct 20, 2013 at 12:47 PM, Torsten Bögershausen tbo...@web.de wrote:
 I'm not sure how to handle overlong path in general, there are several ways:
 a) Silently overwrite memory (with help of memcpy() and/or strcpy()
 b) Silently shorten the path using strlcpy() instead of strcpy()
 c) Avoid the overwriting and call die().
 d) Prepare a longer buffer using xmalloc()

d+) Use strbuf
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-20 Thread Antoine Pelisse
My main motive was to not *stop* the process when a long path is met.
Because somebody created a repository on Linux with a long file-name
doesn't mean you should not be able to clone it *at all* on Windows.

On Sun, Oct 20, 2013 at 12:33 PM, Duy Nguyen pclo...@gmail.com wrote:
 On Sun, Oct 20, 2013 at 12:47 PM, Torsten Bögershausen tbo...@web.de wrote:
 I'm not sure how to handle overlong path in general, there are several ways:
 a) Silently overwrite memory (with help of memcpy() and/or strcpy()

This one stop the process, as the application crashes :-)

 b) Silently shorten the path using strlcpy() instead of strcpy()

I was expecting this solution to fail later in a non-blocking way
(e.g. Can't checkout file $truncated_path, continuing with other
files). Maybe it would be better to look at each specific call site
and see if there is a way to report a problem ('return error(Can't
checkout %s: path too long)')

 c) Avoid the overwriting and call die().

This one also stops the process, with an error (of course that's
better than point a)

 d) Prepare a longer buffer using xmalloc()
 d+) Use strbuf

This of course looks like the best solution, but I believe PATH_MAX
exists for a reason, and maybe we can't simply ignore that value ?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-20 Thread Duy Nguyen
On Mon, Oct 21, 2013 at 12:57 AM, Antoine Pelisse apeli...@gmail.com wrote:
 My main motive was to not *stop* the process when a long path is met.
 Because somebody created a repository on Linux with a long file-name
 doesn't mean you should not be able to clone it *at all* on Windows.

That should be handled at the Windows compatibility layer if Windows
cannot handle long paths as Linux (or maybe at higher level to skip
checking out those paths). For PATH_MAX value, see [1].

[1] http://thread.gmane.org/gmane.comp.version-control.git/169012/focus=169310
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [msysGit] [PATCH] Prevent buffer overflows when path is too big

2013-10-19 Thread Torsten Bögershausen
(may be s/path is too big/path is too long/ ?)

On 19.10.13 12:52, Antoine Pelisse wrote:
 Currently, most buffers created with PATH_MAX length, are not checked
 when being written, and can overflow if PATH_MAX is not big enough to
 hold the path.
 
 Fix that by using strlcpy() where strcpy() was used, and also run some
 extra checks when copy is done with memcpy().
 
 Reported-by: Wataru Noguchi wnoguchi.0...@gmail.com
 Signed-off-by: Antoine Pelisse apeli...@gmail.com
 ---
  abspath.c| 10 +++---
  diffcore-order.c |  2 +-
  entry.c  | 14 ++
  unpack-trees.c   |  2 ++
  4 files changed, 20 insertions(+), 8 deletions(-)
 
 diff --git a/abspath.c b/abspath.c
 index 64adbe2..0e60ba4 100644
 --- a/abspath.c
 +++ b/abspath.c
 @@ -216,11 +216,15 @@ const char *absolute_path(const char *path)
  const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
  {
   static char path[PATH_MAX];
 +
 + if (pfx_len  PATH_MAX)
I think this should be 
if (pfx_len  PATH_MAX-1) /* Keep 1 char for '\0'
 + die(Too long prefix path: %s, pfx);
 +
  #ifndef GIT_WINDOWS_NATIVE
   if (!pfx_len || is_absolute_path(arg))
   return arg;
   memcpy(path, pfx, pfx_len);
 - strcpy(path + pfx_len, arg);
 + strlcpy(path + pfx_len, arg, PATH_MAX - pfx_len);

I'm not sure how to handle overlong path in general, there are several ways:
a) Silently overwrite memory (with help of memcpy() and/or strcpy()
b) Silently shorten the path using strlcpy() instead of strcpy()
c) Avoid the overwriting and call die().
d) Prepare a longer buffer using xmalloc()

Today we do a), this is not a good thing and the worst choice.


A little side note:
  It would be good to have test cases for either b), c) or d).

  As PATH_MAX is OS dependend, we need both a main program written in c
  and a test case written in t/t.sh.
  Some existing code can be used for inspiration, e.g. 
  test-wildmatch.c in combination with t/t3070-wildmatch.sh
  This willl allow us to reproduce the error, and define how git should behave.

End of the side note, let's look closer at the suggested patch, implementing b)

Silently shortening an overlong path like
/foo/bar/baz could result something like

/foo/bar/ba /* That filename may be part of the repo too */
or
/foo/bar/ /*  This is a directory, not a file name */

In either case the end user has no idea why git choose another file name.
And this could be hard to debug.
After a couple of hours she/he may send a message asking for help to the 
mailing list,
and we end up in more people doing debugging.

c) Is much easier to debug:
  Git can not handle this situation, and we print out the parameters in die()

I would prefer c) over b), make clear that git can't handle that situation.

d) Would mean some more re-factoring: Check all callers to prefix_filename().
Some of them call xstrdup() after prefix_filename(), which mean that we could
change prefix_filename() to always return new string which is long enough via 
xmalloc(),
and not a static buffer.

So we come to the next point (and this is my personal experience,
so please don't get me wrong):
how much time can you spend on this?

If the answer is kind of very little, I would go for c)
  Avoid the silent memory corruption, and say to the user we can not handle 
this

If the answer is kind of little, I would go for c) and a test program,
  covering all the different code path in abspath()
  (WHich may deserve a refactoring as well, since the code for 
GIT_WINDOWS_NATIVE
  is very similar to the non-GIT_WINDOWS_NATIVE)

If the answer is kind of more than little, a different strategie may be 
better:
  Start sending a patch for c)
  I think we have enough volunteers here for a review, so we can life without 
the test code.
  On top of that, some volunteer can develop d).
  
So far I have only looked at abspath(), and your patch touches more places.
I think more and more that calling die()
with all information included why we call die() is a good starting point.

It will allow the users to see what is going on.
May be the repo can be re-arranged to use shorter path names than what we can 
handle.
[snip]
 
/Torsten

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html