fsck: warn about symlinked dotfiles we'll open with O_NOFOLLOW

In the commits merged in via 204333b015 (Merge branch 'jk/open-dotgitx-with-nofollow', 2021-03-22), we stopped following symbolic links for .gitattributes, .gitignore, and .mailmap files. Let's teach fsck to warn that these symlinks are not going to do anything. Note that this is just a warning, and won't block the objects via transfer.fsckObjects, since there are reported to be cases of this in the wild (and even once fixed, they will continue to exist in the commit history of those projects, but are not particularly dangerous). Note that we won't add these to the existing gitmodules block in the fsck code. The logic for gitmodules is a bit more complicated, as we also check the content of non-symlink instances we find. But for these new files, there is no content check; we're just looking at the name and mode of the tree entry (and we can avoid even the complicated name checks in the common case that the mode doesn't indicate a symlink). We can reuse the test helper function we defined for .gitmodules, though (it needs some slight adjustments for the fsck error code, and because we don't block these symlinks via verify_path()). Note that I didn't explicitly test the transfer.fsckObjects case here (nor does the existing .gitmodules test that it blocks a push). The translation of fsck severities to outcomes is covered in general in t5504. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed May 3, 2021 at 16:43 UTC bb6832d5529a75164acca7c0412657c96a9a5764
3 files changed +48 -2
fsck.c
+18
@@ -614,6 +614,24 @@ static int fsck_tree(const struct object_id *tree_oid,
614 ".gitmodules is a symbolic link");
615 }
616
617 + if (S_ISLNK(mode)) {
618 + if (is_hfs_dotgitignore(name) ||
619 + is_ntfs_dotgitignore(name))
620 + retval += report(options, tree_oid, OBJ_TREE,
621 + FSCK_MSG_GITIGNORE_SYMLINK,
622 + ".gitignore is a symlink");
623 + if (is_hfs_dotgitattributes(name) ||
624 + is_ntfs_dotgitattributes(name))
625 + retval += report(options, tree_oid, OBJ_TREE,
626 + FSCK_MSG_GITATTRIBUTES_SYMLINK,
627 + ".gitattributes is a symlink");
628 + if (is_hfs_dotmailmap(name) ||
629 + is_ntfs_dotmailmap(name))
630 + retval += report(options, tree_oid, OBJ_TREE,
631 + FSCK_MSG_MAILMAP_SYMLINK,
632 + ".mailmap is a symlink");
633 + }
634 +
635 if ((backslash = strchr(name, '\\'))) {
636 while (backslash) {
637 backslash++;
fsck.h
+3
@@ -67,6 +67,9 @@ enum fsck_msg_type {
67 FUNC(NUL_IN_COMMIT, WARN) \
68 /* infos (reported as warnings, but ignored by default) */ \
69 FUNC(GITMODULES_PARSE, INFO) \
70 + FUNC(GITIGNORE_SYMLINK, INFO) \
71 + FUNC(GITATTRIBUTES_SYMLINK, INFO) \
72 + FUNC(MAILMAP_SYMLINK, INFO) \
73 FUNC(BAD_TAG_NAME, INFO) \
74 FUNC(MISSING_TAGGER_ENTRY, INFO) \
75 /* ignored (elevated when requested) */ \
t/t7450-bad-git-dotfiles.sh
+27 -2
@@ -140,6 +140,18 @@ test_expect_success 'index-pack --strict works for non-repo pack' '
140 '
141
142 check_dotx_symlink () {
143 + fsck_must_fail=test_must_fail
144 + fsck_prefix=error
145 + refuse_index=t
146 + case "$1" in
147 + --warning)
148 + fsck_must_fail=
149 + fsck_prefix=warning
150 + refuse_index=
151 + shift
152 + ;;
153 + esac
154 +
155 name=$1
156 type=$2
157 path=$3
@@ -172,11 +184,12 @@ check_dotx_symlink () {
184
185 # Check not only that we fail, but that it is due to the
186 # symlink detector
175 - test_must_fail git fsck 2>output &&
176 - grep "tree $tree: ${name}Symlink" output
187 + $fsck_must_fail git fsck 2>output &&
188 + grep "$fsck_prefix.*tree $tree: ${name}Symlink" output
189 )
190 '
191
192 + test -n "$refuse_index" &&
193 test_expect_success "refuse to load symlinked $name into index ($type)" '
194 test_must_fail \
195 git -C $dir \
@@ -193,6 +206,18 @@ check_dotx_symlink gitmodules vanilla .gitmodules
206 check_dotx_symlink gitmodules ntfs ".gitmodules ."
207 check_dotx_symlink gitmodules hfs ".${u200c}gitmodules"
208
209 +check_dotx_symlink --warning gitattributes vanilla .gitattributes
210 +check_dotx_symlink --warning gitattributes ntfs ".gitattributes ."
211 +check_dotx_symlink --warning gitattributes hfs ".${u200c}gitattributes"
212 +
213 +check_dotx_symlink --warning gitignore vanilla .gitignore
214 +check_dotx_symlink --warning gitignore ntfs ".gitignore ."
215 +check_dotx_symlink --warning gitignore hfs ".${u200c}gitignore"
216 +
217 +check_dotx_symlink --warning mailmap vanilla .mailmap
218 +check_dotx_symlink --warning mailmap ntfs ".mailmap ."
219 +check_dotx_symlink --warning mailmap hfs ".${u200c}mailmap"
220 +
221 test_expect_success 'fsck detects non-blob .gitmodules' '
222 git init non-blob &&
223 (