]> git.ipfire.org Git - thirdparty/git.git/commitdiff
exclude: do not respect symlinks for in-tree .gitignore
authorJeff King <peff@peff.net>
Tue, 16 Feb 2021 14:44:34 +0000 (09:44 -0500)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Feb 2021 17:41:33 +0000 (09:41 -0800)
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>
dir.c
t/t0008-ignores.sh

diff --git a/dir.c b/dir.c
index f7fb1db7189c7b3d3fb31009bade92c78f91a0a9..3692a281863f073c3b677996ac000b14233e9053 100644 (file)
--- a/dir.c
+++ b/dir.c
@@ -1035,6 +1035,9 @@ static int add_patterns_from_buffer(char *buf, size_t size,
                                    const char *base, int baselen,
                                    struct pattern_list *pl);
 
+/* Flags for add_patterns() */
+#define PATTERN_NOFOLLOW (1<<0)
+
 /*
  * Given a file with name "fname", read it (either from disk, or from
  * 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,
        size_t size = 0;
        char *buf;
 
-       fd = open(fname, O_RDONLY);
+       if (flags & PATTERN_NOFOLLOW)
+               fd = open_nofollow(fname, O_RDONLY);
+       else
+               fd = open(fname, O_RDONLY);
+
        if (fd < 0 || fstat(fd, &st) < 0) {
                if (fd < 0)
                        warn_on_fopen_errors(fname);
@@ -1558,7 +1565,8 @@ static void prep_exclude(struct dir_struct *dir,
                        strbuf_addbuf(&sb, &dir->basebuf);
                        strbuf_addstr(&sb, dir->exclude_per_dir);
                        pl->src = strbuf_detach(&sb, NULL);
-                       add_patterns(pl->src, pl->src, stk->baselen, pl, istate, 0,
+                       add_patterns(pl->src, pl->src, stk->baselen, pl, istate,
+                                    PATTERN_NOFOLLOW,
                                     untracked ? &oid_stat : NULL);
                }
                /*
index 370a389e5c5c509b51189e23b81c6ce2d1b79a18..854cfda11f0842012c8b4d78c974aec92d53451c 100755 (executable)
@@ -865,4 +865,38 @@ test_expect_success 'info/exclude trumps core.excludesfile' '
        test_cmp expect actual
 '
 
+test_expect_success SYMLINKS 'set up ignore file for symlink tests' '
+       echo "*" >ignore &&
+       rm -f .gitignore .git/info/exclude
+'
+
+test_expect_success SYMLINKS 'symlinks respected in core.excludesFile' '
+       test_when_finished "rm symlink" &&
+       ln -s ignore symlink &&
+       test_config core.excludesFile "$(pwd)/symlink" &&
+       echo file >expect &&
+       git check-ignore file >actual 2>err &&
+       test_cmp expect actual &&
+       test_must_be_empty err
+'
+
+test_expect_success SYMLINKS 'symlinks respected in info/exclude' '
+       test_when_finished "rm .git/info/exclude" &&
+       ln -s ../../ignore .git/info/exclude &&
+       echo file >expect &&
+       git check-ignore file >actual 2>err &&
+       test_cmp expect actual &&
+       test_must_be_empty err
+'
+
+test_expect_success SYMLINKS 'symlinks not respected in-tree' '
+       test_when_finished "rm .gitignore" &&
+       ln -s ignore .gitignore &&
+       mkdir subdir &&
+       ln -s ignore subdir/.gitignore &&
+       test_must_fail git check-ignore subdir/file >actual 2>err &&
+       test_must_be_empty actual &&
+       test_i18ngrep "unable to access.*gitignore" err
+'
+
 test_done