summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/git/git/CVE-2020-11008-5.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/git/git/CVE-2020-11008-5.patch')
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-5.patch211
1 files changed, 211 insertions, 0 deletions
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-5.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-5.patch
new file mode 100644
index 0000000000..60f8d59082
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-5.patch
@@ -0,0 +1,211 @@
1From 3431abe8c0f64f4049a31298c0b1056baa7d81dc Mon Sep 17 00:00:00 2001
2From: Li Zhou <li.zhou@windriver.com>
3Date: Mon, 27 Apr 2020 14:45:49 +0800
4Subject: [PATCH 08/12] fsck: convert gitmodules url to URL passed to curl
5
6In 07259e74ec1 (fsck: detect gitmodules URLs with embedded newlines,
72020-03-11), git fsck learned to check whether URLs in .gitmodules could
8be understood by the credential machinery when they are handled by
9git-remote-curl.
10
11However, the check is overbroad: it checks all URLs instead of only
12URLs that would be passed to git-remote-curl. In principle a git:// or
13file:/// URL does not need to follow the same conventions as an http://
14URL; in particular, git:// and file:// protocols are not succeptible to
15issues in the credential API because they do not support attaching
16credentials.
17
18In the HTTP case, the URL in .gitmodules does not always match the URL
19that would be passed to git-remote-curl and the credential machinery:
20Git's URL syntax allows specifying a remote helper followed by a "::"
21delimiter and a URL to be passed to it, so that
22
23 git ls-remote http::https://example.com/repo.git
24
25invokes git-remote-http with https://example.com/repo.git as its URL
26argument. With today's checks, that distinction does not make a
27difference, but for a check we are about to introduce (for empty URL
28schemes) it will matter.
29
30.gitmodules files also support relative URLs. To ensure coverage for the
31https based embedded-newline attack, urldecode and check them directly
32for embedded newlines.
33
34Helped-by: Jeff King <peff@peff.net>
35Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
36Reviewed-by: Jeff King <peff@peff.net>
37
38Upstream-Status: Backport
39CVE: CVE-2020-11008 (5)
40Signed-off-by: Li Zhou <li.zhou@windriver.com>
41---
42 fsck.c | 94 ++++++++++++++++++++++++++++++++++++++++---
43 t/t7416-submodule-dash-url.sh | 29 +++++++++++++
44 2 files changed, 118 insertions(+), 5 deletions(-)
45
46diff --git a/fsck.c b/fsck.c
47index ea46eea..0f21eb1 100644
48--- a/fsck.c
49+++ b/fsck.c
50@@ -9,6 +9,7 @@
51 #include "tag.h"
52 #include "fsck.h"
53 #include "refs.h"
54+#include "url.h"
55 #include "utf8.h"
56 #include "decorate.h"
57 #include "oidset.h"
58@@ -948,17 +949,100 @@ static int fsck_tag(struct tag *tag, const char *data,
59 return fsck_tag_buffer(tag, data, size, options);
60 }
61
62+/*
63+ * Like builtin/submodule--helper.c's starts_with_dot_slash, but without
64+ * relying on the platform-dependent is_dir_sep helper.
65+ *
66+ * This is for use in checking whether a submodule URL is interpreted as
67+ * relative to the current directory on any platform, since \ is a
68+ * directory separator on Windows but not on other platforms.
69+ */
70+static int starts_with_dot_slash(const char *str)
71+{
72+ return str[0] == '.' && (str[1] == '/' || str[1] == '\\');
73+}
74+
75+/*
76+ * Like starts_with_dot_slash, this is a variant of submodule--helper's
77+ * helper of the same name with the twist that it accepts backslash as a
78+ * directory separator even on non-Windows platforms.
79+ */
80+static int starts_with_dot_dot_slash(const char *str)
81+{
82+ return str[0] == '.' && starts_with_dot_slash(str + 1);
83+}
84+
85+static int submodule_url_is_relative(const char *url)
86+{
87+ return starts_with_dot_slash(url) || starts_with_dot_dot_slash(url);
88+}
89+
90+/*
91+ * Check whether a transport is implemented by git-remote-curl.
92+ *
93+ * If it is, returns 1 and writes the URL that would be passed to
94+ * git-remote-curl to the "out" parameter.
95+ *
96+ * Otherwise, returns 0 and leaves "out" untouched.
97+ *
98+ * Examples:
99+ * http::https://example.com/repo.git -> 1, https://example.com/repo.git
100+ * https://example.com/repo.git -> 1, https://example.com/repo.git
101+ * git://example.com/repo.git -> 0
102+ *
103+ * This is for use in checking for previously exploitable bugs that
104+ * required a submodule URL to be passed to git-remote-curl.
105+ */
106+static int url_to_curl_url(const char *url, const char **out)
107+{
108+ /*
109+ * We don't need to check for case-aliases, "http.exe", and so
110+ * on because in the default configuration, is_transport_allowed
111+ * prevents URLs with those schemes from being cloned
112+ * automatically.
113+ */
114+ if (skip_prefix(url, "http::", out) ||
115+ skip_prefix(url, "https::", out) ||
116+ skip_prefix(url, "ftp::", out) ||
117+ skip_prefix(url, "ftps::", out))
118+ return 1;
119+ if (starts_with(url, "http://") ||
120+ starts_with(url, "https://") ||
121+ starts_with(url, "ftp://") ||
122+ starts_with(url, "ftps://")) {
123+ *out = url;
124+ return 1;
125+ }
126+ return 0;
127+}
128+
129 static int check_submodule_url(const char *url)
130 {
131- struct credential c = CREDENTIAL_INIT;
132- int ret;
133+ const char *curl_url;
134
135 if (looks_like_command_line_option(url))
136 return -1;
137
138- ret = credential_from_url_gently(&c, url, 1);
139- credential_clear(&c);
140- return ret;
141+ if (submodule_url_is_relative(url)) {
142+ /*
143+ * This could be appended to an http URL and url-decoded;
144+ * check for malicious characters.
145+ */
146+ char *decoded = url_decode(url);
147+ int has_nl = !!strchr(decoded, '\n');
148+ free(decoded);
149+ if (has_nl)
150+ return -1;
151+ }
152+
153+ else if (url_to_curl_url(url, &curl_url)) {
154+ struct credential c = CREDENTIAL_INIT;
155+ int ret = credential_from_url_gently(&c, curl_url, 1);
156+ credential_clear(&c);
157+ return ret;
158+ }
159+
160+ return 0;
161 }
162
163 struct fsck_gitmodules_data {
164diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
165index 41431b1..afdd255 100755
166--- a/t/t7416-submodule-dash-url.sh
167+++ b/t/t7416-submodule-dash-url.sh
168@@ -60,6 +60,20 @@ test_expect_success 'trailing backslash is handled correctly' '
169 test_i18ngrep ! "unknown option" err
170 '
171
172+test_expect_success 'fsck permits embedded newline with unrecognized scheme' '
173+ git checkout --orphan newscheme &&
174+ cat >.gitmodules <<-\EOF &&
175+ [submodule "foo"]
176+ url = "data://acjbkd%0akajfdickajkd"
177+ EOF
178+ git add .gitmodules &&
179+ git commit -m "gitmodules with unrecognized scheme" &&
180+ test_when_finished "rm -rf dst" &&
181+ git init --bare dst &&
182+ git -C dst config transfer.fsckObjects true &&
183+ git push dst HEAD
184+'
185+
186 test_expect_success 'fsck rejects embedded newline in url' '
187 # create an orphan branch to avoid existing .gitmodules objects
188 git checkout --orphan newline &&
189@@ -76,4 +90,19 @@ test_expect_success 'fsck rejects embedded newline in url' '
190 grep gitmodulesUrl err
191 '
192
193+test_expect_success 'fsck rejects embedded newline in relative url' '
194+ git checkout --orphan relative-newline &&
195+ cat >.gitmodules <<-\EOF &&
196+ [submodule "foo"]
197+ url = "./%0ahost=two.example.com/foo.git"
198+ EOF
199+ git add .gitmodules &&
200+ git commit -m "relative url with newline" &&
201+ test_when_finished "rm -rf dst" &&
202+ git init --bare dst &&
203+ git -C dst config transfer.fsckObjects true &&
204+ test_must_fail git push dst HEAD 2>err &&
205+ grep gitmodulesUrl err
206+'
207+
208 test_done
209--
2101.9.1
211