From: "Glen Choo via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Taylor Blau <me@ttaylorr.com>, Glen Choo <chooglen@google.com>,
Glen Choo <chooglen@google.com>
Subject: [PATCH v2] clone: error specifically with --local and symlinked objects
Date: Mon, 10 Apr 2023 22:18:50 +0000 [thread overview]
Message-ID: <pull.1488.v2.git.git.1681165130765.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1488.git.git.1680652122547.gitgitgadget@gmail.com>
From: Glen Choo <chooglen@google.com>
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>
---
clone: error specifically with --local and symlinked objects
Thanks for the close review on v1, folks.
I tried teaching dir_iterator_begin() to return an exit code to indicate
that we found a symlink, but it ended up looking quite ugly when I
started to consider plain files as well as generic lstat failures. I
think the extra lstat() is fine as a one-off, but if we need another
instance of this, we'd be better off doing the refactor.
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-git-1488%2Fchooglen%2Fpush-nymnqqnttzxz-v2
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-git-1488/chooglen/push-nymnqqnttzxz-v2
Pull-Request: https://github.com/git/git/pull/1488
Range-diff vs v1:
1: 5c2d5eb10cd ! 1: 574cea062cf clone: error specifically with --local and symlinked objects
@@ builtin/clone.c: static void copy_or_link_directory(struct strbuf *src, struct s
- if (!iter)
+ if (!iter) {
-+ struct stat st;
-+ if (lstat(src->buf, &st) >= 0 && S_ISLNK(st.st_mode))
-+ die(_("'%s' is a symlink, refusing to clone with --local"),
-+ src->buf);
++ if (errno == ENOTDIR) {
++ int saved_errno = errno;
++ struct stat st;
++ if (lstat(src->buf, &st) == 0 && 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);
+ }
Documentation/git-clone.txt | 5 +++++
builtin/clone.c | 11 ++++++++++-
t/t5604-clone-reference.sh | 2 +-
3 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index d6434d262d6..c37c4a37f74 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 462c286274c..46f6f689c85 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -327,8 +327,17 @@ 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) == 0 && 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 83e3c97861d..9845fc04d59 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
base-commit: 27d43aaaf50ef0ae014b88bba294f93658016a2e
--
gitgitgadget
next prev parent reply other threads:[~2023-04-10 22:18 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-04-04 23:48 [PATCH] clone: error specifically with --local and symlinked objects Glen Choo via GitGitGadget
2023-04-05 0:13 ` Junio C Hamano
2023-04-05 16:48 ` Glen Choo
2023-04-05 19:20 ` Junio C Hamano
2023-04-06 21:35 ` Taylor Blau
2023-04-06 21:55 ` Glen Choo
2023-04-06 21:27 ` Taylor Blau
2023-04-10 22:18 ` Glen Choo via GitGitGadget [this message]
2023-04-10 22:27 ` [PATCH v2] " Junio C Hamano
2023-04-10 23:16 ` Taylor Blau
2023-04-11 1:58 ` Taylor Blau
2023-04-11 17:08 ` [PATCH v3] " Glen Choo via GitGitGadget
2023-04-11 17:13 ` Junio C Hamano
2023-04-11 18:38 ` Glen Choo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=pull.1488.v2.git.git.1681165130765.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=chooglen@google.com \
--cc=git@vger.kernel.org \
--cc=me@ttaylorr.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.