exclude: do not respect symlinks for in-tree .gitignore
As with .gitattributes, we would like to make sure that .gitignore files are handled consistently whether read from the index or from the filesystem. Likewise, we would like to avoid reading out-of-tree files pointed to by the symlinks, which could have security implications in certain setups. We can cover both by using open_nofollow() when opening the in-tree files. We'll continue to follow links for core.excludesFile, as well as $GIT_DIR/info/exclude. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Feb 16, 2021 at 09:44 UTC
feb9b7792f0963a818f825bd99be4cda4e8226a5
2 files changed
+44
-2
dir.c
+10
-2
@@ -1035,6 +1035,9 @@ static int add_patterns_from_buffer(char *buf, size_t size,
1035
const char *base, int baselen,
1036
struct pattern_list *pl);
1037
1038
+/* Flags for add_patterns() */
1039
+#define PATTERN_NOFOLLOW (1<<0)
1040
+
1041
/*
1042
* Given a file with name "fname", read it (either from disk, or from
1043
* an index if 'istate' is non-null), parse it and store the
@@ -1054,7 +1057,11 @@ static int add_patterns(const char *fname, const char *base, int baselen,
1057
size_t size = 0;
1058
char *buf;
1059
1057
- fd = open(fname, O_RDONLY);
1060
+ if (flags & PATTERN_NOFOLLOW)
1061
+ fd = open_nofollow(fname, O_RDONLY);
1062
+ else
1063
+ fd = open(fname, O_RDONLY);
1064
+
1065
if (fd < 0 || fstat(fd, &st) < 0) {
1066
if (fd < 0)
1067
warn_on_fopen_errors(fname);
@@ -1558,7 +1565,8 @@ static void prep_exclude(struct dir_struct *dir,
1565
strbuf_addbuf(&sb, &dir->basebuf);
1566
strbuf_addstr(&sb, dir->exclude_per_dir);
1567
pl->src = strbuf_detach(&sb, NULL);
1561
- add_patterns(pl->src, pl->src, stk->baselen, pl, istate, 0,
1568
+ add_patterns(pl->src, pl->src, stk->baselen, pl, istate,
1569
+ PATTERN_NOFOLLOW,
1570
untracked ? &oid_stat : NULL);
1571
}
1572
/*
t/t0008-ignores.sh
+34
@@ -865,4 +865,38 @@ test_expect_success 'info/exclude trumps core.excludesfile' '
865
test_cmp expect actual
866
'
867
868
+test_expect_success SYMLINKS 'set up ignore file for symlink tests' '
869
+ echo "*" >ignore &&
870
+ rm -f .gitignore .git/info/exclude
871
+'
872
+
873
+test_expect_success SYMLINKS 'symlinks respected in core.excludesFile' '
874
+ test_when_finished "rm symlink" &&
875
+ ln -s ignore symlink &&
876
+ test_config core.excludesFile "$(pwd)/symlink" &&
877
+ echo file >expect &&
878
+ git check-ignore file >actual 2>err &&
879
+ test_cmp expect actual &&
880
+ test_must_be_empty err
881
+'
882
+
883
+test_expect_success SYMLINKS 'symlinks respected in info/exclude' '
884
+ test_when_finished "rm .git/info/exclude" &&
885
+ ln -s ../../ignore .git/info/exclude &&
886
+ echo file >expect &&
887
+ git check-ignore file >actual 2>err &&
888
+ test_cmp expect actual &&
889
+ test_must_be_empty err
890
+'
891
+
892
+test_expect_success SYMLINKS 'symlinks not respected in-tree' '
893
+ test_when_finished "rm .gitignore" &&
894
+ ln -s ignore .gitignore &&
895
+ mkdir subdir &&
896
+ ln -s ignore subdir/.gitignore &&
897
+ test_must_fail git check-ignore subdir/file >actual 2>err &&
898
+ test_must_be_empty actual &&
899
+ test_i18ngrep "unable to access.*gitignore" err
900
+'
901
+
902
test_done