Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/attr.c
diff options
context:
space:
mode:
authorJeff King <peff@peff.net>2021-02-16 17:44:32 +0300
committerJunio C Hamano <gitster@pobox.com>2021-02-16 20:41:33 +0300
commit2ef579e261fcd85a4eb6e0ce98ee4a01625fc210 (patch)
treec9309bb2a6590875cdd87c223cc081e5d5ad8e2e /attr.c
parent1679d60bfc4c5c38f30fc938cf006b1e8608f733 (diff)
attr: do not respect symlinks for in-tree .gitattributes
The attributes system may sometimes read in-tree files from the filesystem, and sometimes from the index. In the latter case, we do not resolve symbolic links (and are not likely to ever start doing so). Let's open filesystem links with O_NOFOLLOW so that the two cases behave consistently. As a bonus, this means that git will not follow such symlinks to read and parse out-of-tree paths. In some cases this could have security implications, as a malicious repository can cause Git to open and read arbitrary files. It could already feed arbitrary content to the parser, but in certain setups it might be able to exfiltrate data from those paths (e.g., if an automated service operating on the malicious repo reveals its stderr to an attacker). Note that O_NOFOLLOW only prevents following links for the path itself, not intermediate directories in the path. At first glance, it seems like ln -s /some/path in-repo might still look at "in-repo/.gitattributes", following the symlink to "/some/path/.gitattributes". However, if "in-repo" is a symbolic link, then we know that it has no git paths below it, and will never look at its .gitattributes file. We will continue to support out-of-tree symbolic links (e.g., in $GIT_DIR/info/attributes); this just affects in-tree links. When a symbolic link is encountered, the contents are ignored and a warning is printed. POSIX specifies ELOOP in this case, so the user would generally see something like: warning: unable to access '.gitattributes': Too many levels of symbolic links Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'attr.c')
-rw-r--r--attr.c19
1 files changed, 15 insertions, 4 deletions
diff --git a/attr.c b/attr.c
index 7b0cab085f..a28177915b 100644
--- a/attr.c
+++ b/attr.c
@@ -280,6 +280,7 @@ static const char blank[] = " \t\r\n";
/* Flags usable in read_attr() and parse_attr_line() family of functions. */
#define READ_ATTR_MACRO_OK (1<<0)
+#define READ_ATTR_NOFOLLOW (1<<1)
/*
* Parse a whitespace-delimited attribute state (i.e., "attr",
@@ -704,13 +705,23 @@ void git_attr_set_direction(enum git_attr_direction new_direction)
static struct attr_stack *read_attr_from_file(const char *path, unsigned flags)
{
- FILE *fp = fopen_or_warn(path, "r");
+ int fd;
+ FILE *fp;
struct attr_stack *res;
char buf[2048];
int lineno = 0;
- if (!fp)
+ if (flags & READ_ATTR_NOFOLLOW)
+ fd = open_nofollow(path, O_RDONLY);
+ else
+ fd = open(path, O_RDONLY);
+
+ if (fd < 0) {
+ warn_on_fopen_errors(path);
return NULL;
+ }
+ fp = xfdopen(fd, "r");
+
res = xcalloc(1, sizeof(*res));
while (fgets(buf, sizeof(buf), fp)) {
char *bufp = buf;
@@ -870,7 +881,7 @@ static void bootstrap_attr_stack(const struct index_state *istate,
}
/* root directory */
- e = read_attr(istate, GITATTRIBUTES_FILE, flags);
+ e = read_attr(istate, GITATTRIBUTES_FILE, flags | READ_ATTR_NOFOLLOW);
push_stack(stack, e, xstrdup(""), 0);
/* info frame */
@@ -961,7 +972,7 @@ static void prepare_attr_stack(const struct index_state *istate,
strbuf_add(&pathbuf, path + pathbuf.len, (len - pathbuf.len));
strbuf_addf(&pathbuf, "/%s", GITATTRIBUTES_FILE);
- next = read_attr(istate, pathbuf.buf, 0);
+ next = read_attr(istate, pathbuf.buf, READ_ATTR_NOFOLLOW);
/* reset the pathbuf to not include "/.gitattributes" */
strbuf_setlen(&pathbuf, len);