summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2023-04-20 14:33:36 -0700
committerJunio C Hamano <gitster@pobox.com>2023-04-20 14:33:36 -0700
commita4a4db8cf7024b31ecd4b2c59cdcac41e81c91a2 (patch)
tree708c8bd597b1bc45bcc5a68d7355c1843163a476
parent98c496fcd09b5894966f3e499217eb2bdf8b964d (diff)
parent4e33535ea98ac16d2163e8e9fcbba5e015881e65 (diff)
Merge branch 'gc/better-error-when-local-clone-fails-with-symlink'
"git clone --local" stops copying from an original repository that has symbolic links inside its $GIT_DIR; an error message when that happens has been updated. * gc/better-error-when-local-clone-fails-with-symlink: clone: error specifically with --local and symlinked objects
-rw-r--r--Documentation/git-clone.txt5
-rw-r--r--builtin/clone.c12
-rwxr-xr-xt/t5604-clone-reference.sh2
3 files changed, 17 insertions, 2 deletions
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index d6434d262d..c37c4a37f7 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -58,6 +58,11 @@ never use the local optimizations). Specifying `--no-local` will
override the default when `/path/to/repo` is given, using the regular
Git transport instead.
+
+If the repository's `$GIT_DIR/objects` has symbolic links or is a
+symbolic link, the clone will fail. This is a security measure to
+prevent the unintentional copying of files by dereferencing the symbolic
+links.
++
*NOTE*: this operation can race with concurrent modification to the
source repository, similar to running `cp -r src dst` while modifying
`src`.
diff --git a/builtin/clone.c b/builtin/clone.c
index 6dc89f1058..eeec8067ec 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -331,8 +331,18 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
iter = dir_iterator_begin(src->buf, DIR_ITERATOR_PEDANTIC);
- if (!iter)
+ if (!iter) {
+ if (errno == ENOTDIR) {
+ int saved_errno = errno;
+ struct stat st;
+
+ if (!lstat(src->buf, &st) && S_ISLNK(st.st_mode))
+ die(_("'%s' is a symlink, refusing to clone with --local"),
+ src->buf);
+ errno = saved_errno;
+ }
die_errno(_("failed to start iterator over '%s'"), src->buf);
+ }
strbuf_addch(src, '/');
src_len = src->len;
diff --git a/t/t5604-clone-reference.sh b/t/t5604-clone-reference.sh
index 83e3c97861..9845fc04d5 100755
--- a/t/t5604-clone-reference.sh
+++ b/t/t5604-clone-reference.sh
@@ -358,7 +358,7 @@ test_expect_success SYMLINKS 'clone repo with symlinked objects directory' '
test_must_fail git clone --local malicious clone 2>err &&
test_path_is_missing clone &&
- grep "failed to start iterator over" err
+ grep "is a symlink, refusing to clone with --local" err
'
test_done