Skip to content

Commit a54e938

Browse files
rscharfegitster
authored andcommitted
strbuf: support long paths w/o read rights in strbuf_getcwd() on FreeBSD
FreeBSD implements getcwd(3) as a syscall, but falls back to a version based on readdir(3) if it fails for some reason. The latter requires permissions to read and execute path components, while the former does not. That means that if our buffer is too small and we're missing rights we could get EACCES, but we may succeed with a bigger buffer. Keep retrying if getcwd(3) indicates lack of permissions until our buffer can fit PATH_MAX bytes, as that's the maximum supported by the syscall on FreeBSD anyway. This way we do what we can to be able to benefit from the syscall, but we also won't loop forever if there is a real permission issue. This fixes a regression introduced with 7333ed1 (setup: convert setup_git_directory_gently_1 et al. to strbuf, 2014-07-28) for paths longer than 127 bytes with components that miss read or execute permissions (e.g. 0711 on /home for privacy reasons); we used a fixed PATH_MAX-sized buffer before. Reported-by: Zenobiusz Kunegunda <[email protected]> Signed-off-by: Rene Scharfe <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 8f9aeb0 commit a54e938

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

strbuf.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,17 @@ int strbuf_getcwd(struct strbuf *sb)
449449
strbuf_setlen(sb, strlen(sb->buf));
450450
return 0;
451451
}
452+
453+
/*
454+
* If getcwd(3) is implemented as a syscall that falls
455+
* back to a regular lookup using readdir(3) etc. then
456+
* we may be able to avoid EACCES by providing enough
457+
* space to the syscall as it's not necessarily bound
458+
* to the same restrictions as the fallback.
459+
*/
460+
if (errno == EACCES && guessed_len < PATH_MAX)
461+
continue;
462+
452463
if (errno != ERANGE)
453464
break;
454465
}

t/t0001-init.sh

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,20 @@ test_expect_success 'init with separate gitdir' '
315315
test_path_is_dir realgitdir/refs
316316
'
317317

318+
test_expect_success 'init in long base path' '
319+
# exceed initial buffer size of strbuf_getcwd()
320+
component=123456789abcdef &&
321+
test_when_finished "chmod 0700 $component; rm -rf $component" &&
322+
p31=$component/$component &&
323+
p127=$p31/$p31/$p31/$p31 &&
324+
mkdir -p $p127 &&
325+
chmod 0111 $component &&
326+
(
327+
cd $p127 &&
328+
git init newdir
329+
)
330+
'
331+
318332
test_expect_success 're-init on .git file' '
319333
( cd newdir && git init )
320334
'

0 commit comments

Comments
 (0)