Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTaylor Blau <me@ttaylorr.com>2023-01-25 03:43:51 +0300
committerJunio C Hamano <gitster@pobox.com>2023-01-25 03:52:16 +0300
commitbffc762f87ae8d18c6001bf0044a76004245754c (patch)
tree94ef671b634c0516c9643aa5e685ca31c0793453 /dir-iterator.c
parentcf8f6ce02a13f4d1979a53241afbee15a293fce9 (diff)
dir-iterator: prevent top-level symlinks without FOLLOW_SYMLINKS
When using the dir_iterator API, we first stat(2) the base path, and then use that as a starting point to enumerate the directory's contents. If the directory contains symbolic links, we will immediately die() upon encountering them without the `FOLLOW_SYMLINKS` flag. The same is not true when resolving the top-level directory, though. As explained in a previous commit, this oversight in 6f054f9fb3 (builtin/clone.c: disallow `--local` clones with symlinks, 2022-07-28) can be used as an attack vector to include arbitrary files on a victim's filesystem from outside of the repository. Prevent resolving top-level symlinks unless the FOLLOW_SYMLINKS flag is given, which will cause clones of a repository with a symlink'd "$GIT_DIR/objects" directory to fail. Signed-off-by: Taylor Blau <me@ttaylorr.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'dir-iterator.c')
-rw-r--r--dir-iterator.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/dir-iterator.c b/dir-iterator.c
index b17e9f970a..3764dd81a1 100644
--- a/dir-iterator.c
+++ b/dir-iterator.c
@@ -203,7 +203,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags)
{
struct dir_iterator_int *iter = xcalloc(1, sizeof(*iter));
struct dir_iterator *dir_iterator = &iter->base;
- int saved_errno;
+ int saved_errno, err;
strbuf_init(&iter->base.path, PATH_MAX);
strbuf_addstr(&iter->base.path, path);
@@ -213,10 +213,15 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags)
iter->flags = flags;
/*
- * Note: stat already checks for NULL or empty strings and
- * inexistent paths.
+ * Note: stat/lstat already checks for NULL or empty strings and
+ * nonexistent paths.
*/
- if (stat(iter->base.path.buf, &iter->base.st) < 0) {
+ if (iter->flags & DIR_ITERATOR_FOLLOW_SYMLINKS)
+ err = stat(iter->base.path.buf, &iter->base.st);
+ else
+ err = lstat(iter->base.path.buf, &iter->base.st);
+
+ if (err < 0) {
saved_errno = errno;
goto error_out;
}