diff options
| author | Junio C Hamano <gitster@pobox.com> | 2023-04-20 14:33:36 -0700 |
|---|---|---|
| committer | Junio C Hamano <gitster@pobox.com> | 2023-04-20 14:33:36 -0700 |
| commit | a4a4db8cf7024b31ecd4b2c59cdcac41e81c91a2 (patch) | |
| tree | 708c8bd597b1bc45bcc5a68d7355c1843163a476 | |
| parent | 98c496fcd09b5894966f3e499217eb2bdf8b964d (diff) | |
| parent | 4e33535ea98ac16d2163e8e9fcbba5e015881e65 (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.txt | 5 | ||||
| -rw-r--r-- | builtin/clone.c | 12 | ||||
| -rwxr-xr-x | t/t5604-clone-reference.sh | 2 |
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 |
