]> git.ipfire.org Git - thirdparty/git.git/commitdiff
clone: error specifically with --local and symlinked objects
authorGlen Choo <chooglen@google.com>
Mon, 10 Apr 2023 22:18:50 +0000 (22:18 +0000)
committerJunio C Hamano <gitster@pobox.com>
Tue, 11 Apr 2023 15:46:09 +0000 (08:46 -0700)
6f054f9fb3 (builtin/clone.c: disallow --local clones with
symlinks, 2022-07-28) gives a good error message when "git clone
--local" fails when the repo to clone has symlinks in
"$GIT_DIR/objects". In bffc762f87 (dir-iterator: prevent top-level
symlinks without FOLLOW_SYMLINKS, 2023-01-24), we later extended this
restriction to the case where "$GIT_DIR/objects" is itself a symlink,
but we didn't update the error message then - bffc762f87's tests show
that we print a generic "failed to start iterator over" message.

This is exacerbated by the fact that Documentation/git-clone.txt
mentions neither restriction, so users are left wondering if this is
intentional behavior or not.

Fix this by adding a check to builtin/clone.c: when doing a local clone,
perform an extra check to see if "$GIT_DIR/objects" is a symlink, and if
so, assume that that was the reason for the failure and report the
relevant information. Ideally, dir_iterator_begin() would tell us that
the real failure reason is the presence of the symlink, but (as far as I
can tell) there isn't an appropriate errno value for that.

Also, update Documentation/git-clone.txt to reflect that this
restriction exists.

Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/git-clone.txt
builtin/clone.c
t/t5604-clone-reference.sh

index d6434d262d6e2945ffe98f397ab8500a53990750..c37c4a37f7412c0b712d14067c2d7c7d975933c5 100644 (file)
@@ -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`.
index c171def1f3edf2dd11bf545d7d7b84d8e9c62ff7..ae2db8535aa3a8120e47c7d1ff148d51ae6378f2 100644 (file)
@@ -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;
index 83e3c97861ddc50eb9e6b1a78e68d693224c3fc9..9845fc04d59809acc17dbe7c8a122c93b84d4f75 100755 (executable)
@@ -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