summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/git
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/git')
-rw-r--r--meta/recipes-devtools/git/git.inc16
-rw-r--r--meta/recipes-devtools/git/git/0001-t-lib-credential-use-test_i18ncmp-to-check-stderr.patch35
-rw-r--r--meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch156
-rw-r--r--meta/recipes-devtools/git/git/0003-fsck-detect-gitmodules-URLs-with-embedded-newlines.patch103
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-1.patch70
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-2.patch292
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-3.patch97
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-4.patch173
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-5.patch211
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-6.patch84
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-7.patch206
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-8.patch114
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-11008-9.patch114
-rw-r--r--meta/recipes-devtools/git/git/CVE-2020-5260.patch65
14 files changed, 1735 insertions, 1 deletions
diff --git a/meta/recipes-devtools/git/git.inc b/meta/recipes-devtools/git/git.inc
index 6e137432f0..a0ce1626a1 100644
--- a/meta/recipes-devtools/git/git.inc
+++ b/meta/recipes-devtools/git/git.inc
@@ -7,7 +7,21 @@ DEPENDS = "openssl curl zlib expat"
7PROVIDES_append_class-native = " git-replacement-native" 7PROVIDES_append_class-native = " git-replacement-native"
8 8
9SRC_URI = "${KERNELORG_MIRROR}/software/scm/git/git-${PV}.tar.gz;name=tarball \ 9SRC_URI = "${KERNELORG_MIRROR}/software/scm/git/git-${PV}.tar.gz;name=tarball \
10 ${KERNELORG_MIRROR}/software/scm/git/git-manpages-${PV}.tar.gz;name=manpages" 10 ${KERNELORG_MIRROR}/software/scm/git/git-manpages-${PV}.tar.gz;name=manpages \
11 file://CVE-2020-5260.patch \
12 file://0001-t-lib-credential-use-test_i18ncmp-to-check-stderr.patch \
13 file://0002-credential-detect-unrepresentable-values-when-parsin.patch \
14 file://0003-fsck-detect-gitmodules-URLs-with-embedded-newlines.patch \
15 file://CVE-2020-11008-1.patch \
16 file://CVE-2020-11008-2.patch \
17 file://CVE-2020-11008-3.patch \
18 file://CVE-2020-11008-4.patch \
19 file://CVE-2020-11008-5.patch \
20 file://CVE-2020-11008-6.patch \
21 file://CVE-2020-11008-7.patch \
22 file://CVE-2020-11008-8.patch \
23 file://CVE-2020-11008-9.patch \
24 "
11 25
12S = "${WORKDIR}/git-${PV}" 26S = "${WORKDIR}/git-${PV}"
13 27
diff --git a/meta/recipes-devtools/git/git/0001-t-lib-credential-use-test_i18ncmp-to-check-stderr.patch b/meta/recipes-devtools/git/git/0001-t-lib-credential-use-test_i18ncmp-to-check-stderr.patch
new file mode 100644
index 0000000000..6eb3c16aef
--- /dev/null
+++ b/meta/recipes-devtools/git/git/0001-t-lib-credential-use-test_i18ncmp-to-check-stderr.patch
@@ -0,0 +1,35 @@
1From 70ef9c6ce884b2d466d3d36563f1d2aa31b56443 Mon Sep 17 00:00:00 2001
2From: Jeff King <peff@peff.net>
3Date: Wed, 11 Mar 2020 18:11:37 -0400
4Subject: [PATCH 01/12] t/lib-credential: use test_i18ncmp to check stderr
5
6The credential tests have a "check" function which feeds some input to
7git-credential and checks the stdout and stderr. We look for exact
8matches in the output. For stdout, this makes sense; the output is
9the credential protocol. But for stderr, we may be showing various
10diagnostic messages, or the prompts fed to the askpass program, which
11could be translated. Let's mark them as such.
12
13Upstream-Status: Backport
14
15Signed-off-by: Li Zhou <li.zhou@windriver.com>
16---
17 t/lib-credential.sh | 2 +-
18 1 file changed, 1 insertion(+), 1 deletion(-)
19
20diff --git a/t/lib-credential.sh b/t/lib-credential.sh
21index 937b831..bb88cc0 100755
22--- a/t/lib-credential.sh
23+++ b/t/lib-credential.sh
24@@ -19,7 +19,7 @@ check() {
25 false
26 fi &&
27 test_cmp expect-stdout stdout &&
28- test_cmp expect-stderr stderr
29+ test_i18ncmp expect-stderr stderr
30 }
31
32 read_chunk() {
33--
341.9.1
35
diff --git a/meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch b/meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch
new file mode 100644
index 0000000000..a9b7348ef7
--- /dev/null
+++ b/meta/recipes-devtools/git/git/0002-credential-detect-unrepresentable-values-when-parsin.patch
@@ -0,0 +1,156 @@
1From 43803880b954a020dbffa5250a5b7fd893442c7c Mon Sep 17 00:00:00 2001
2From: Jeff King <peff@peff.net>
3Date: Thu, 12 Mar 2020 01:31:11 -0400
4Subject: [PATCH 02/12] credential: detect unrepresentable values when parsing
5 urls
6
7The credential protocol can't represent newlines in values, but URLs can
8embed percent-encoded newlines in various components. A previous commit
9taught the low-level writing routines to die() when encountering this,
10but we can be a little friendlier to the user by detecting them earlier
11and handling them gracefully.
12
13This patch teaches credential_from_url() to notice such components,
14issue a warning, and blank the credential (which will generally result
15in prompting the user for a username and password). We blank the whole
16credential in this case. Another option would be to blank only the
17invalid component. However, we're probably better off not feeding a
18partially-parsed URL result to a credential helper. We don't know how a
19given helper would handle it, so we're better off to err on the side of
20matching nothing rather than something unexpected.
21
22The die() call in credential_write() is _probably_ impossible to reach
23after this patch. Values should end up in credential structs only by URL
24parsing (which is covered here), or by reading credential protocol input
25(which by definition cannot read a newline into a value). But we should
26definitely keep the low-level check, as it's our final and most accurate
27line of defense against protocol injection attacks. Arguably it could
28become a BUG(), but it probably doesn't matter much either way.
29
30Note that the public interface of credential_from_url() grows a little
31more than we need here. We'll use the extra flexibility in a future
32patch to help fsck catch these cases.
33
34Upstream-Status: Backport
35
36Signed-off-by: Li Zhou <li.zhou@windriver.com>
37---
38 credential.c | 36 ++++++++++++++++++++++++++++++++++--
39 credential.h | 16 ++++++++++++++++
40 t/t0300-credentials.sh | 12 ++++++++++--
41 3 files changed, 60 insertions(+), 4 deletions(-)
42
43diff --git a/credential.c b/credential.c
44index a79aff0..2482382 100644
45--- a/credential.c
46+++ b/credential.c
47@@ -324,7 +324,22 @@ void credential_reject(struct credential *c)
48 c->approved = 0;
49 }
50
51-void credential_from_url(struct credential *c, const char *url)
52+static int check_url_component(const char *url, int quiet,
53+ const char *name, const char *value)
54+{
55+ if (!value)
56+ return 0;
57+ if (!strchr(value, '\n'))
58+ return 0;
59+
60+ if (!quiet)
61+ warning(_("url contains a newline in its %s component: %s"),
62+ name, url);
63+ return -1;
64+}
65+
66+int credential_from_url_gently(struct credential *c, const char *url,
67+ int quiet)
68 {
69 const char *at, *colon, *cp, *slash, *host, *proto_end;
70
71@@ -338,7 +353,7 @@ void credential_from_url(struct credential *c, const char *url)
72 */
73 proto_end = strstr(url, "://");
74 if (!proto_end)
75- return;
76+ return 0;
77 cp = proto_end + 3;
78 at = strchr(cp, '@');
79 colon = strchr(cp, ':');
80@@ -373,4 +388,21 @@ void credential_from_url(struct credential *c, const char *url)
81 while (p > c->path && *p == '/')
82 *p-- = '\0';
83 }
84+
85+ if (check_url_component(url, quiet, "username", c->username) < 0 ||
86+ check_url_component(url, quiet, "password", c->password) < 0 ||
87+ check_url_component(url, quiet, "protocol", c->protocol) < 0 ||
88+ check_url_component(url, quiet, "host", c->host) < 0 ||
89+ check_url_component(url, quiet, "path", c->path) < 0)
90+ return -1;
91+
92+ return 0;
93+}
94+
95+void credential_from_url(struct credential *c, const char *url)
96+{
97+ if (credential_from_url_gently(c, url, 0) < 0) {
98+ warning(_("skipping credential lookup for url: %s"), url);
99+ credential_clear(c);
100+ }
101 }
102diff --git a/credential.h b/credential.h
103index 6b0cd16..122a23c 100644
104--- a/credential.h
105+++ b/credential.h
106@@ -28,7 +28,23 @@ struct credential {
107
108 int credential_read(struct credential *, FILE *);
109 void credential_write(const struct credential *, FILE *);
110+
111+/*
112+ * Parse a url into a credential struct, replacing any existing contents.
113+ *
114+ * Ifthe url can't be parsed (e.g., a missing "proto://" component), the
115+ * resulting credential will be empty but we'll still return success from the
116+ * "gently" form.
117+ *
118+ * If we encounter a component which cannot be represented as a credential
119+ * value (e.g., because it contains a newline), the "gently" form will return
120+ * an error but leave the broken state in the credential object for further
121+ * examination. The non-gentle form will issue a warning to stderr and return
122+ * an empty credential.
123+ */
124 void credential_from_url(struct credential *, const char *url);
125+int credential_from_url_gently(struct credential *, const char *url, int quiet);
126+
127 int credential_match(const struct credential *have,
128 const struct credential *want);
129
130diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
131index 26f3c3a..b9c0f1f 100755
132--- a/t/t0300-credentials.sh
133+++ b/t/t0300-credentials.sh
134@@ -308,9 +308,17 @@ test_expect_success 'empty helper spec resets helper list' '
135 EOF
136 '
137
138-test_expect_success 'url parser rejects embedded newlines' '
139- test_must_fail git credential fill <<-\EOF
140+test_expect_success 'url parser ignores embedded newlines' '
141+ check fill <<-EOF
142 url=https://one.example.com?%0ahost=two.example.com/
143+ --
144+ username=askpass-username
145+ password=askpass-password
146+ --
147+ warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/
148+ warning: skipping credential lookup for url: https://one.example.com?%0ahost=two.example.com/
149+ askpass: Username:
150+ askpass: Password:
151 EOF
152 '
153
154--
1551.9.1
156
diff --git a/meta/recipes-devtools/git/git/0003-fsck-detect-gitmodules-URLs-with-embedded-newlines.patch b/meta/recipes-devtools/git/git/0003-fsck-detect-gitmodules-URLs-with-embedded-newlines.patch
new file mode 100644
index 0000000000..23931e6313
--- /dev/null
+++ b/meta/recipes-devtools/git/git/0003-fsck-detect-gitmodules-URLs-with-embedded-newlines.patch
@@ -0,0 +1,103 @@
1From 1c9f8cedd34302575db40016231bdf502f17901e Mon Sep 17 00:00:00 2001
2From: Li Zhou <li.zhou@windriver.com>
3Date: Mon, 27 Apr 2020 13:49:39 +0800
4Subject: [PATCH 03/12] fsck: detect gitmodules URLs with embedded newlines
5
6The credential protocol can't handle values with newlines. We already
7detect and block any such URLs from being used with credential helpers,
8but let's also add an fsck check to detect and block gitmodules files
9with such URLs. That will let us notice the problem earlier when
10transfer.fsckObjects is turned on. And in particular it will prevent bad
11objects from spreading, which may protect downstream users running older
12versions of Git.
13
14We'll file this under the existing gitmodulesUrl flag, which covers URLs
15with option injection. There's really no need to distinguish the exact
16flaw in the URL in this context. Likewise, I've expanded the description
17of t7416 to cover all types of bogus URLs.
18
19Upstream-Status: Backport
20
21Signed-off-by: Li Zhou <li.zhou@windriver.com>
22---
23 fsck.c | 16 +++++++++++++++-
24 t/t7416-submodule-dash-url.sh | 18 +++++++++++++++++-
25 2 files changed, 32 insertions(+), 2 deletions(-)
26
27diff --git a/fsck.c b/fsck.c
28index ef8b343..ea46eea 100644
29--- a/fsck.c
30+++ b/fsck.c
31@@ -15,6 +15,7 @@
32 #include "packfile.h"
33 #include "submodule-config.h"
34 #include "config.h"
35+#include "credential.h"
36 #include "help.h"
37
38 static struct oidset gitmodules_found = OIDSET_INIT;
39@@ -947,6 +948,19 @@ static int fsck_tag(struct tag *tag, const char *data,
40 return fsck_tag_buffer(tag, data, size, options);
41 }
42
43+static int check_submodule_url(const char *url)
44+{
45+ struct credential c = CREDENTIAL_INIT;
46+ int ret;
47+
48+ if (looks_like_command_line_option(url))
49+ return -1;
50+
51+ ret = credential_from_url_gently(&c, url, 1);
52+ credential_clear(&c);
53+ return ret;
54+}
55+
56 struct fsck_gitmodules_data {
57 struct object *obj;
58 struct fsck_options *options;
59@@ -971,7 +985,7 @@ static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata)
60 "disallowed submodule name: %s",
61 name);
62 if (!strcmp(key, "url") && value &&
63- looks_like_command_line_option(value))
64+ check_submodule_url(value) < 0)
65 data->ret |= report(data->options, data->obj,
66 FSCK_MSG_GITMODULES_URL,
67 "disallowed submodule url: %s",
68diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
69index 5ba041f..41431b1 100755
70--- a/t/t7416-submodule-dash-url.sh
71+++ b/t/t7416-submodule-dash-url.sh
72@@ -1,6 +1,6 @@
73 #!/bin/sh
74
75-test_description='check handling of .gitmodule url with dash'
76+test_description='check handling of disallowed .gitmodule urls'
77 . ./test-lib.sh
78
79 test_expect_success 'create submodule with protected dash in url' '
80@@ -60,4 +60,20 @@ test_expect_success 'trailing backslash is handled correctly' '
81 test_i18ngrep ! "unknown option" err
82 '
83
84+test_expect_success 'fsck rejects embedded newline in url' '
85+ # create an orphan branch to avoid existing .gitmodules objects
86+ git checkout --orphan newline &&
87+ cat >.gitmodules <<-\EOF &&
88+ [submodule "foo"]
89+ url = "https://one.example.com?%0ahost=two.example.com/foo.git"
90+ EOF
91+ git add .gitmodules &&
92+ git commit -m "gitmodules with newline" &&
93+ test_when_finished "rm -rf dst" &&
94+ git init --bare dst &&
95+ git -C dst config transfer.fsckObjects true &&
96+ test_must_fail git push dst HEAD 2>err &&
97+ grep gitmodulesUrl err
98+'
99+
100 test_done
101--
1021.9.1
103
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-1.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-1.patch
new file mode 100644
index 0000000000..9cf98ea7b4
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-1.patch
@@ -0,0 +1,70 @@
1From 863f8067d8b4012904ca3bb881c659ac9894df97 Mon Sep 17 00:00:00 2001
2From: Li Zhou <li.zhou@windriver.com>
3Date: Mon, 27 Apr 2020 14:36:03 +0800
4Subject: [PATCH 04/12] t0300: make "quit" helper more realistic
5
6We test a toy credential helper that writes "quit=1" and confirms that
7we stop running other helpers. However, that helper is unrealistic in
8that it does not bother to read its stdin at all.
9
10For now we don't send any input to it, because we feed git-credential a
11blank credential. But that will change in the next patch, which will
12cause this test to racily fail, as git-credential will get SIGPIPE
13writing to the helper rather than exiting because it was asked to.
14
15Let's make this one-off helper more like our other sample helpers, and
16have it source the "dump" script. That will read stdin, fixing the
17SIGPIPE problem. But it will also write what it sees to stderr. We can
18make the test more robust by checking that output, which confirms that
19we do run the quit helper, don't run any other helpers, and exit for the
20reason we expected.
21
22Signed-off-by: Jeff King <peff@peff.net>
23Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
24
25Upstream-Status: Backport
26CVE: CVE-2020-11008 (1)
27Signed-off-by: Li Zhou <li.zhou@windriver.com>
28---
29 t/t0300-credentials.sh | 17 ++++++++++++++---
30 1 file changed, 14 insertions(+), 3 deletions(-)
31
32diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
33index b9c0f1f..0206b3b 100755
34--- a/t/t0300-credentials.sh
35+++ b/t/t0300-credentials.sh
36@@ -22,6 +22,11 @@ test_expect_success 'setup helper scripts' '
37 exit 0
38 EOF
39
40+ write_script git-credential-quit <<-\EOF &&
41+ . ./dump
42+ echo quit=1
43+ EOF
44+
45 write_script git-credential-verbatim <<-\EOF &&
46 user=$1; shift
47 pass=$1; shift
48@@ -291,10 +296,16 @@ test_expect_success 'http paths can be part of context' '
49
50 test_expect_success 'helpers can abort the process' '
51 test_must_fail git \
52- -c credential.helper="!f() { echo quit=1; }; f" \
53+ -c credential.helper=quit \
54 -c credential.helper="verbatim foo bar" \
55- credential fill >stdout &&
56- test_must_be_empty stdout
57+ credential fill >stdout 2>stderr &&
58+ >expect &&
59+ test_cmp expect stdout &&
60+ cat >expect <<-\EOF &&
61+ quit: get
62+ fatal: credential helper '\''quit'\'' told us to quit
63+ EOF
64+ test_i18ncmp expect stderr
65 '
66
67 test_expect_success 'empty helper spec resets helper list' '
68--
691.9.1
70
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-2.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-2.patch
new file mode 100644
index 0000000000..c752e3d431
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-2.patch
@@ -0,0 +1,292 @@
1From 5588659069214aa0f7fea75a69687078e2f7a817 Mon Sep 17 00:00:00 2001
2From: Jeff King <peff@peff.net>
3Date: Sat, 18 Apr 2020 20:47:30 -0700
4Subject: [PATCH 05/12] t0300: use more realistic inputs
5
6Many of the tests in t0300 give partial inputs to git-credential,
7omitting a protocol or hostname. We're checking only high-level things
8like whether and how helpers are invoked at all, and we don't care about
9specific hosts. However, in preparation for tightening up the rules
10about when we're willing to run a helper, let's start using input that's
11a bit more realistic: pretend as if http://example.com is being
12examined.
13
14This shouldn't change the point of any of the tests, but do note we have
15to adjust the expected output to accommodate this (filling a credential
16will repeat back the protocol/host fields to stdout, and the helper
17debug messages and askpass prompt will change on stderr).
18
19Signed-off-by: Jeff King <peff@peff.net>
20Reviewed-by: Taylor Blau <me@ttaylorr.com>
21Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
22
23Upstream-Status: Backport
24CVE: CVE-2020-11008 (2)
25Signed-off-by: Li Zhou <li.zhou@windriver.com>
26---
27 t/t0300-credentials.sh | 89 +++++++++++++++++++++++++++++++++++++++++++++++---
28 1 file changed, 85 insertions(+), 4 deletions(-)
29
30diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
31index 0206b3b..f4c5d7f 100755
32--- a/t/t0300-credentials.sh
33+++ b/t/t0300-credentials.sh
34@@ -40,43 +40,71 @@ test_expect_success 'setup helper scripts' '
35
36 test_expect_success 'credential_fill invokes helper' '
37 check fill "verbatim foo bar" <<-\EOF
38+ protocol=http
39+ host=example.com
40 --
41+ protocol=http
42+ host=example.com
43 username=foo
44 password=bar
45 --
46 verbatim: get
47+ verbatim: protocol=http
48+ verbatim: host=example.com
49 EOF
50 '
51
52 test_expect_success 'credential_fill invokes multiple helpers' '
53 check fill useless "verbatim foo bar" <<-\EOF
54+ protocol=http
55+ host=example.com
56 --
57+ protocol=http
58+ host=example.com
59 username=foo
60 password=bar
61 --
62 useless: get
63+ useless: protocol=http
64+ useless: host=example.com
65 verbatim: get
66+ verbatim: protocol=http
67+ verbatim: host=example.com
68 EOF
69 '
70
71 test_expect_success 'credential_fill stops when we get a full response' '
72 check fill "verbatim one two" "verbatim three four" <<-\EOF
73+ protocol=http
74+ host=example.com
75 --
76+ protocol=http
77+ host=example.com
78 username=one
79 password=two
80 --
81 verbatim: get
82+ verbatim: protocol=http
83+ verbatim: host=example.com
84 EOF
85 '
86
87 test_expect_success 'credential_fill continues through partial response' '
88 check fill "verbatim one \"\"" "verbatim two three" <<-\EOF
89+ protocol=http
90+ host=example.com
91 --
92+ protocol=http
93+ host=example.com
94 username=two
95 password=three
96 --
97 verbatim: get
98+ verbatim: protocol=http
99+ verbatim: host=example.com
100 verbatim: get
101+ verbatim: protocol=http
102+ verbatim: host=example.com
103 verbatim: username=one
104 EOF
105 '
106@@ -102,14 +130,20 @@ test_expect_success 'credential_fill passes along metadata' '
107
108 test_expect_success 'credential_approve calls all helpers' '
109 check approve useless "verbatim one two" <<-\EOF
110+ protocol=http
111+ host=example.com
112 username=foo
113 password=bar
114 --
115 --
116 useless: store
117+ useless: protocol=http
118+ useless: host=example.com
119 useless: username=foo
120 useless: password=bar
121 verbatim: store
122+ verbatim: protocol=http
123+ verbatim: host=example.com
124 verbatim: username=foo
125 verbatim: password=bar
126 EOF
127@@ -117,6 +151,8 @@ test_expect_success 'credential_approve calls all helpers' '
128
129 test_expect_success 'do not bother storing password-less credential' '
130 check approve useless <<-\EOF
131+ protocol=http
132+ host=example.com
133 username=foo
134 --
135 --
136@@ -126,14 +162,20 @@ test_expect_success 'do not bother storing password-less credential' '
137
138 test_expect_success 'credential_reject calls all helpers' '
139 check reject useless "verbatim one two" <<-\EOF
140+ protocol=http
141+ host=example.com
142 username=foo
143 password=bar
144 --
145 --
146 useless: erase
147+ useless: protocol=http
148+ useless: host=example.com
149 useless: username=foo
150 useless: password=bar
151 verbatim: erase
152+ verbatim: protocol=http
153+ verbatim: host=example.com
154 verbatim: username=foo
155 verbatim: password=bar
156 EOF
157@@ -141,33 +183,49 @@ test_expect_success 'credential_reject calls all helpers' '
158
159 test_expect_success 'usernames can be preserved' '
160 check fill "verbatim \"\" three" <<-\EOF
161+ protocol=http
162+ host=example.com
163 username=one
164 --
165+ protocol=http
166+ host=example.com
167 username=one
168 password=three
169 --
170 verbatim: get
171+ verbatim: protocol=http
172+ verbatim: host=example.com
173 verbatim: username=one
174 EOF
175 '
176
177 test_expect_success 'usernames can be overridden' '
178 check fill "verbatim two three" <<-\EOF
179+ protocol=http
180+ host=example.com
181 username=one
182 --
183+ protocol=http
184+ host=example.com
185 username=two
186 password=three
187 --
188 verbatim: get
189+ verbatim: protocol=http
190+ verbatim: host=example.com
191 verbatim: username=one
192 EOF
193 '
194
195 test_expect_success 'do not bother completing already-full credential' '
196 check fill "verbatim three four" <<-\EOF
197+ protocol=http
198+ host=example.com
199 username=one
200 password=two
201 --
202+ protocol=http
203+ host=example.com
204 username=one
205 password=two
206 --
207@@ -179,23 +237,31 @@ test_expect_success 'do not bother completing already-full credential' '
208 # askpass helper is run, we know the internal getpass is working.
209 test_expect_success 'empty helper list falls back to internal getpass' '
210 check fill <<-\EOF
211+ protocol=http
212+ host=example.com
213 --
214+ protocol=http
215+ host=example.com
216 username=askpass-username
217 password=askpass-password
218 --
219- askpass: Username:
220- askpass: Password:
221+ askpass: Username for '\''http://example.com'\'':
222+ askpass: Password for '\''http://askpass-username@example.com'\'':
223 EOF
224 '
225
226 test_expect_success 'internal getpass does not ask for known username' '
227 check fill <<-\EOF
228+ protocol=http
229+ host=example.com
230 username=foo
231 --
232+ protocol=http
233+ host=example.com
234 username=foo
235 password=askpass-password
236 --
237- askpass: Password:
238+ askpass: Password for '\''http://foo@example.com'\'':
239 EOF
240 '
241
242@@ -207,7 +273,11 @@ HELPER="!f() {
243 test_expect_success 'respect configured credentials' '
244 test_config credential.helper "$HELPER" &&
245 check fill <<-\EOF
246+ protocol=http
247+ host=example.com
248 --
249+ protocol=http
250+ host=example.com
251 username=foo
252 password=bar
253 --
254@@ -298,11 +368,16 @@ test_expect_success 'helpers can abort the process' '
255 test_must_fail git \
256 -c credential.helper=quit \
257 -c credential.helper="verbatim foo bar" \
258- credential fill >stdout 2>stderr &&
259+ credential fill >stdout 2>stderr <<-\EOF &&
260+ protocol=http
261+ host=example.com
262+ EOF
263 >expect &&
264 test_cmp expect stdout &&
265 cat >expect <<-\EOF &&
266 quit: get
267+ quit: protocol=http
268+ quit: host=example.com
269 fatal: credential helper '\''quit'\'' told us to quit
270 EOF
271 test_i18ncmp expect stderr
272@@ -311,11 +386,17 @@ test_expect_success 'helpers can abort the process' '
273 test_expect_success 'empty helper spec resets helper list' '
274 test_config credential.helper "verbatim file file" &&
275 check fill "" "verbatim cmdline cmdline" <<-\EOF
276+ protocol=http
277+ host=example.com
278 --
279+ protocol=http
280+ host=example.com
281 username=cmdline
282 password=cmdline
283 --
284 verbatim: get
285+ verbatim: protocol=http
286+ verbatim: host=example.com
287 EOF
288 '
289
290--
2911.9.1
292
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-3.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-3.patch
new file mode 100644
index 0000000000..c17e883d6c
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-3.patch
@@ -0,0 +1,97 @@
1From 22f28251ae575dd7a60f7a46853469025d004ca7 Mon Sep 17 00:00:00 2001
2From: Jeff King <peff@peff.net>
3Date: Sat, 18 Apr 2020 20:48:05 -0700
4Subject: [PATCH 06/12] credential: parse URL without host as empty host, not
5 unset
6
7We may feed a URL like "cert:///path/to/cert.pem" into the credential
8machinery to get the key for a client-side certificate. That
9credential has no hostname field, which is about to be disallowed (to
10avoid confusion with protocols where a helper _would_ expect a
11hostname).
12
13This means as of the next patch, credential helpers won't work for
14unlocking certs. Let's fix that by doing two things:
15
16 - when we parse a url with an empty host, set the host field to the
17 empty string (asking only to match stored entries with an empty
18 host) rather than NULL (asking to match _any_ host).
19
20 - when we build a cert:// credential by hand, similarly assign an
21 empty string
22
23It's the latter that is more likely to impact real users in practice,
24since it's what's used for http connections. But we don't have good
25infrastructure to test it.
26
27The url-parsing version will help anybody using git-credential in a
28script, and is easy to test.
29
30Signed-off-by: Jeff King <peff@peff.net>
31Reviewed-by: Taylor Blau <me@ttaylorr.com>
32Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
33
34Upstream-Status: Backport
35CVE: CVE-2020-11008 (3)
36Signed-off-by: Li Zhou <li.zhou@windriver.com>
37---
38 credential.c | 3 +--
39 http.c | 1 +
40 t/t0300-credentials.sh | 17 +++++++++++++++++
41 3 files changed, 19 insertions(+), 2 deletions(-)
42
43diff --git a/credential.c b/credential.c
44index 2482382..f2413ce 100644
45--- a/credential.c
46+++ b/credential.c
47@@ -376,8 +376,7 @@ int credential_from_url_gently(struct credential *c, const char *url,
48
49 if (proto_end - url > 0)
50 c->protocol = xmemdupz(url, proto_end - url);
51- if (slash - host > 0)
52- c->host = url_decode_mem(host, slash - host);
53+ c->host = url_decode_mem(host, slash - host);
54 /* Trim leading and trailing slashes from path */
55 while (*slash == '/')
56 slash++;
57diff --git a/http.c b/http.c
58index 27aa0a3..c4dfdac 100644
59--- a/http.c
60+++ b/http.c
61@@ -558,6 +558,7 @@ static int has_cert_password(void)
62 return 0;
63 if (!cert_auth.password) {
64 cert_auth.protocol = xstrdup("cert");
65+ cert_auth.host = xstrdup("");
66 cert_auth.username = xstrdup("");
67 cert_auth.path = xstrdup(ssl_cert);
68 credential_fill(&cert_auth);
69diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
70index f4c5d7f..1c1010b 100755
71--- a/t/t0300-credentials.sh
72+++ b/t/t0300-credentials.sh
73@@ -414,4 +414,21 @@ test_expect_success 'url parser ignores embedded newlines' '
74 EOF
75 '
76
77+test_expect_success 'host-less URLs are parsed as empty host' '
78+ check fill "verbatim foo bar" <<-\EOF
79+ url=cert:///path/to/cert.pem
80+ --
81+ protocol=cert
82+ host=
83+ path=path/to/cert.pem
84+ username=foo
85+ password=bar
86+ --
87+ verbatim: get
88+ verbatim: protocol=cert
89+ verbatim: host=
90+ verbatim: path=path/to/cert.pem
91+ EOF
92+'
93+
94 test_done
95--
961.9.1
97
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-4.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-4.patch
new file mode 100644
index 0000000000..14e23466d4
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-4.patch
@@ -0,0 +1,173 @@
1From f8bf7099379990ad974c1ca8f51e1f28bf18cf2a Mon Sep 17 00:00:00 2001
2From: Jeff King <peff@peff.net>
3Date: Sat, 18 Apr 2020 20:50:48 -0700
4Subject: [PATCH 07/12] credential: refuse to operate when missing host or
5 protocol
6
7The credential helper protocol was designed to be very flexible: the
8fields it takes as input are treated as a pattern, and any missing
9fields are taken as wildcards. This allows unusual things like:
10
11 echo protocol=https | git credential reject
12
13to delete all stored https credentials (assuming the helpers themselves
14treat the input that way). But when helpers are invoked automatically by
15Git, this flexibility works against us. If for whatever reason we don't
16have a "host" field, then we'd match _any_ host. When you're filling a
17credential to send to a remote server, this is almost certainly not what
18you want.
19
20Prevent this at the layer that writes to the credential helper. Add a
21check to the credential API that the host and protocol are always passed
22in, and add an assertion to the credential_write function that speaks
23credential helper protocol to be doubly sure.
24
25There are a few ways this can be triggered in practice:
26
27 - the "git credential" command passes along arbitrary credential
28 parameters it reads from stdin.
29
30 - until the previous patch, when the host field of a URL is empty, we
31 would leave it unset (rather than setting it to the empty string)
32
33 - a URL like "example.com/foo.git" is treated by curl as if "http://"
34 was present, but our parser sees it as a non-URL and leaves all
35 fields unset
36
37 - the recent fix for URLs with embedded newlines blanks the URL but
38 otherwise continues. Rather than having the desired effect of
39 looking up no credential at all, many helpers will return _any_
40 credential
41
42Our earlier test for an embedded newline didn't catch this because it
43only checked that the credential was cleared, but didn't configure an
44actual helper. Configuring the "verbatim" helper in the test would show
45that it is invoked (it's obviously a silly helper which doesn't look at
46its input, but the point is that it shouldn't be run at all). Since
47we're switching this case to die(), we don't need to bother with a
48helper. We can see the new behavior just by checking that the operation
49fails.
50
51We'll add new tests covering partial input as well (these can be
52triggered through various means with url-parsing, but it's simpler to
53just check them directly, as we know we are covered even if the url
54parser changes behavior in the future).
55
56[jn: changed to die() instead of logging and showing a manual
57 username/password prompt]
58
59Reported-by: Carlo Arenas <carenas@gmail.com>
60Signed-off-by: Jeff King <peff@peff.net>
61Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
62
63Upstream-Status: Backport
64CVE: CVE-2020-11008 (4)
65Signed-off-by: Li Zhou <li.zhou@windriver.com>
66---
67 credential.c | 20 ++++++++++++++------
68 t/t0300-credentials.sh | 34 ++++++++++++++++++++++++++--------
69 2 files changed, 40 insertions(+), 14 deletions(-)
70
71diff --git a/credential.c b/credential.c
72index f2413ce..e08ed84 100644
73--- a/credential.c
74+++ b/credential.c
75@@ -89,6 +89,11 @@ static int proto_is_http(const char *s)
76
77 static void credential_apply_config(struct credential *c)
78 {
79+ if (!c->host)
80+ die(_("refusing to work with credential missing host field"));
81+ if (!c->protocol)
82+ die(_("refusing to work with credential missing protocol field"));
83+
84 if (c->configured)
85 return;
86 git_config(credential_config_callback, c);
87@@ -191,8 +196,11 @@ int credential_read(struct credential *c, FILE *fp)
88 return 0;
89 }
90
91-static void credential_write_item(FILE *fp, const char *key, const char *value)
92+static void credential_write_item(FILE *fp, const char *key, const char *value,
93+ int required)
94 {
95+ if (!value && required)
96+ BUG("credential value for %s is missing", key);
97 if (!value)
98 return;
99 if (strchr(value, '\n'))
100@@ -202,11 +210,11 @@ static void credential_write_item(FILE *fp, const char *key, const char *value)
101
102 void credential_write(const struct credential *c, FILE *fp)
103 {
104- credential_write_item(fp, "protocol", c->protocol);
105- credential_write_item(fp, "host", c->host);
106- credential_write_item(fp, "path", c->path);
107- credential_write_item(fp, "username", c->username);
108- credential_write_item(fp, "password", c->password);
109+ credential_write_item(fp, "protocol", c->protocol, 1);
110+ credential_write_item(fp, "host", c->host, 1);
111+ credential_write_item(fp, "path", c->path, 0);
112+ credential_write_item(fp, "username", c->username, 0);
113+ credential_write_item(fp, "password", c->password, 0);
114 }
115
116 static int run_credential_helper(struct credential *c,
117diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
118index 1c1010b..646f845 100755
119--- a/t/t0300-credentials.sh
120+++ b/t/t0300-credentials.sh
121@@ -400,18 +400,16 @@ test_expect_success 'empty helper spec resets helper list' '
122 EOF
123 '
124
125-test_expect_success 'url parser ignores embedded newlines' '
126- check fill <<-EOF
127+test_expect_success 'url parser rejects embedded newlines' '
128+ test_must_fail git credential fill 2>stderr <<-\EOF &&
129 url=https://one.example.com?%0ahost=two.example.com/
130- --
131- username=askpass-username
132- password=askpass-password
133- --
134+ EOF
135+ cat >expect <<-\EOF &&
136 warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/
137 warning: skipping credential lookup for url: https://one.example.com?%0ahost=two.example.com/
138- askpass: Username:
139- askpass: Password:
140+ fatal: refusing to work with credential missing host field
141 EOF
142+ test_i18ncmp expect stderr
143 '
144
145 test_expect_success 'host-less URLs are parsed as empty host' '
146@@ -431,4 +429,24 @@ test_expect_success 'host-less URLs are parsed as empty host' '
147 EOF
148 '
149
150+test_expect_success 'credential system refuses to work with missing host' '
151+ test_must_fail git credential fill 2>stderr <<-\EOF &&
152+ protocol=http
153+ EOF
154+ cat >expect <<-\EOF &&
155+ fatal: refusing to work with credential missing host field
156+ EOF
157+ test_i18ncmp expect stderr
158+'
159+
160+test_expect_success 'credential system refuses to work with missing protocol' '
161+ test_must_fail git credential fill 2>stderr <<-\EOF &&
162+ host=example.com
163+ EOF
164+ cat >expect <<-\EOF &&
165+ fatal: refusing to work with credential missing protocol field
166+ EOF
167+ test_i18ncmp expect stderr
168+'
169+
170 test_done
171--
1721.9.1
173
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
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-6.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-6.patch
new file mode 100644
index 0000000000..6b36893030
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-6.patch
@@ -0,0 +1,84 @@
1From 883508bcebe87fbe7fb7392272e930c27c30fdc2 Mon Sep 17 00:00:00 2001
2From: Jeff King <peff@peff.net>
3Date: Sat, 18 Apr 2020 20:53:09 -0700
4Subject: [PATCH 09/12] credential: die() when parsing invalid urls
5
6When we try to initialize credential loading by URL and find that the
7URL is invalid, we set all fields to NULL in order to avoid acting on
8malicious input. Later when we request credentials, we diagonse the
9erroneous input:
10
11 fatal: refusing to work with credential missing host field
12
13This is problematic in two ways:
14
15- The message doesn't tell the user *why* we are missing the host
16 field, so they can't tell from this message alone how to recover.
17 There can be intervening messages after the original warning of
18 bad input, so the user may not have the context to put two and two
19 together.
20
21- The error only occurs when we actually need to get a credential. If
22 the URL permits anonymous access, the only encouragement the user gets
23 to correct their bogus URL is a quiet warning.
24
25 This is inconsistent with the check we perform in fsck, where any use
26 of such a URL as a submodule is an error.
27
28When we see such a bogus URL, let's not try to be nice and continue
29without helpers. Instead, die() immediately. This is simpler and
30obviously safe. And there's very little chance of disrupting a normal
31workflow.
32
33It's _possible_ that somebody has a legitimate URL with a raw newline in
34it. It already wouldn't work with credential helpers, so this patch
35steps that up from an inconvenience to "we will refuse to work with it
36at all". If such a case does exist, we should figure out a way to work
37with it (especially if the newline is only in the path component, which
38we normally don't even pass to helpers). But until we see a real report,
39we're better off being defensive.
40
41Reported-by: Carlo Arenas <carenas@gmail.com>
42Signed-off-by: Jeff King <peff@peff.net>
43Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
44
45Upstream-Status: Backport
46CVE: CVE-2020-11008 (6)
47Signed-off-by: Li Zhou <li.zhou@windriver.com>
48---
49 credential.c | 6 ++----
50 t/t0300-credentials.sh | 3 +--
51 2 files changed, 3 insertions(+), 6 deletions(-)
52
53diff --git a/credential.c b/credential.c
54index e08ed84..22649d5 100644
55--- a/credential.c
56+++ b/credential.c
57@@ -408,8 +408,6 @@ int credential_from_url_gently(struct credential *c, const char *url,
58
59 void credential_from_url(struct credential *c, const char *url)
60 {
61- if (credential_from_url_gently(c, url, 0) < 0) {
62- warning(_("skipping credential lookup for url: %s"), url);
63- credential_clear(c);
64- }
65+ if (credential_from_url_gently(c, url, 0) < 0)
66+ die(_("credential url cannot be parsed: %s"), url);
67 }
68diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
69index 646f845..efed3ea 100755
70--- a/t/t0300-credentials.sh
71+++ b/t/t0300-credentials.sh
72@@ -406,8 +406,7 @@ test_expect_success 'url parser rejects embedded newlines' '
73 EOF
74 cat >expect <<-\EOF &&
75 warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/
76- warning: skipping credential lookup for url: https://one.example.com?%0ahost=two.example.com/
77- fatal: refusing to work with credential missing host field
78+ fatal: credential url cannot be parsed: https://one.example.com?%0ahost=two.example.com/
79 EOF
80 test_i18ncmp expect stderr
81 '
82--
831.9.1
84
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-7.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-7.patch
new file mode 100644
index 0000000000..5e3b6f1454
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-7.patch
@@ -0,0 +1,206 @@
1From 68acf8724e9cb2f67664dd980581c0022401daf0 Mon Sep 17 00:00:00 2001
2From: Jonathan Nieder <jrnieder@gmail.com>
3Date: Sat, 18 Apr 2020 20:54:13 -0700
4Subject: [PATCH 10/12] credential: treat URL without scheme as invalid
5
6libcurl permits making requests without a URL scheme specified. In
7this case, it guesses the URL from the hostname, so I can run
8
9 git ls-remote http::ftp.example.com/path/to/repo
10
11and it would make an FTP request.
12
13Any user intentionally using such a URL is likely to have made a typo.
14Unfortunately, credential_from_url is not able to determine the host and
15protocol in order to determine appropriate credentials to send, and
16until "credential: refuse to operate when missing host or protocol",
17this resulted in another host's credentials being leaked to the named
18host.
19
20Teach credential_from_url_gently to consider such a URL to be invalid
21so that fsck can detect and block gitmodules files with such URLs,
22allowing server operators to avoid serving them to downstream users
23running older versions of Git.
24
25This also means that when such URLs are passed on the command line, Git
26will print a clearer error so affected users can switch to the simpler
27URL that explicitly specifies the host and protocol they intend.
28
29One subtlety: .gitmodules files can contain relative URLs, representing
30a URL relative to the URL they were cloned from. The relative URL
31resolver used for .gitmodules can follow ".." components out of the path
32part and past the host part of a URL, meaning that such a relative URL
33can be used to traverse from a https://foo.example.com/innocent
34superproject to a https::attacker.example.com/exploit submodule.
35Fortunately a leading ':' in the first path component after a series of
36leading './' and '../' components is unlikely to show up in other
37contexts, so we can catch this by detecting that pattern.
38
39Reported-by: Jeff King <peff@peff.net>
40Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
41Reviewed-by: Jeff King <peff@peff.net>
42
43Upstream-Status: Backport
44CVE: CVE-2020-11008 (7)
45Signed-off-by: Li Zhou <li.zhou@windriver.com>
46---
47 credential.c | 7 +++++--
48 fsck.c | 47 +++++++++++++++++++++++++++++++++++++++++--
49 t/t5550-http-fetch-dumb.sh | 7 ++-----
50 t/t7416-submodule-dash-url.sh | 32 +++++++++++++++++++++++++++++
51 4 files changed, 84 insertions(+), 9 deletions(-)
52
53diff --git a/credential.c b/credential.c
54index 22649d5..1e1aed5 100644
55--- a/credential.c
56+++ b/credential.c
57@@ -360,8 +360,11 @@ int credential_from_url_gently(struct credential *c, const char *url,
58 * (3) proto://<user>:<pass>@<host>/...
59 */
60 proto_end = strstr(url, "://");
61- if (!proto_end)
62- return 0;
63+ if (!proto_end) {
64+ if (!quiet)
65+ warning(_("url has no scheme: %s"), url);
66+ return -1;
67+ }
68 cp = proto_end + 3;
69 at = strchr(cp, '@');
70 colon = strchr(cp, ':');
71diff --git a/fsck.c b/fsck.c
72index 0f21eb1..30eac29 100644
73--- a/fsck.c
74+++ b/fsck.c
75@@ -978,6 +978,34 @@ static int submodule_url_is_relative(const char *url)
76 }
77
78 /*
79+ * Count directory components that a relative submodule URL should chop
80+ * from the remote_url it is to be resolved against.
81+ *
82+ * In other words, this counts "../" components at the start of a
83+ * submodule URL.
84+ *
85+ * Returns the number of directory components to chop and writes a
86+ * pointer to the next character of url after all leading "./" and
87+ * "../" components to out.
88+ */
89+static int count_leading_dotdots(const char *url, const char **out)
90+{
91+ int result = 0;
92+ while (1) {
93+ if (starts_with_dot_dot_slash(url)) {
94+ result++;
95+ url += strlen("../");
96+ continue;
97+ }
98+ if (starts_with_dot_slash(url)) {
99+ url += strlen("./");
100+ continue;
101+ }
102+ *out = url;
103+ return result;
104+ }
105+}
106+/*
107 * Check whether a transport is implemented by git-remote-curl.
108 *
109 * If it is, returns 1 and writes the URL that would be passed to
110@@ -1024,15 +1052,30 @@ static int check_submodule_url(const char *url)
111 return -1;
112
113 if (submodule_url_is_relative(url)) {
114+ char *decoded;
115+ const char *next;
116+ int has_nl;
117+
118 /*
119 * This could be appended to an http URL and url-decoded;
120 * check for malicious characters.
121 */
122- char *decoded = url_decode(url);
123- int has_nl = !!strchr(decoded, '\n');
124+ decoded = url_decode(url);
125+ has_nl = !!strchr(decoded, '\n');
126+
127 free(decoded);
128 if (has_nl)
129 return -1;
130+
131+ /*
132+ * URLs which escape their root via "../" can overwrite
133+ * the host field and previous components, resolving to
134+ * URLs like https::example.com/submodule.git that were
135+ * susceptible to CVE-2020-11008.
136+ */
137+ if (count_leading_dotdots(url, &next) > 0 &&
138+ *next == ':')
139+ return -1;
140 }
141
142 else if (url_to_curl_url(url, &curl_url)) {
143diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
144index b811d89..1c9e5d3 100755
145--- a/t/t5550-http-fetch-dumb.sh
146+++ b/t/t5550-http-fetch-dumb.sh
147@@ -321,11 +321,8 @@ test_expect_success 'git client does not send an empty Accept-Language' '
148 '
149
150 test_expect_success 'remote-http complains cleanly about malformed urls' '
151- # do not actually issue "list" or other commands, as we do not
152- # want to rely on what curl would actually do with such a broken
153- # URL. This is just about making sure we do not segfault during
154- # initialization.
155- test_must_fail git remote-http http::/example.com/repo.git
156+ test_must_fail git remote-http http::/example.com/repo.git 2>stderr &&
157+ test_i18ngrep "url has no scheme" stderr
158 '
159
160 test_expect_success 'redirects can be forbidden/allowed' '
161diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
162index afdd255..249dc3d 100755
163--- a/t/t7416-submodule-dash-url.sh
164+++ b/t/t7416-submodule-dash-url.sh
165@@ -60,6 +60,38 @@ test_expect_success 'trailing backslash is handled correctly' '
166 test_i18ngrep ! "unknown option" err
167 '
168
169+test_expect_success 'fsck rejects missing URL scheme' '
170+ git checkout --orphan missing-scheme &&
171+ cat >.gitmodules <<-\EOF &&
172+ [submodule "foo"]
173+ url = http::one.example.com/foo.git
174+ EOF
175+ git add .gitmodules &&
176+ test_tick &&
177+ git commit -m "gitmodules with missing URL scheme" &&
178+ test_when_finished "rm -rf dst" &&
179+ git init --bare dst &&
180+ git -C dst config transfer.fsckObjects true &&
181+ test_must_fail git push dst HEAD 2>err &&
182+ grep gitmodulesUrl err
183+'
184+
185+test_expect_success 'fsck rejects relative URL resolving to missing scheme' '
186+ git checkout --orphan relative-missing-scheme &&
187+ cat >.gitmodules <<-\EOF &&
188+ [submodule "foo"]
189+ url = "..\\../.\\../:one.example.com/foo.git"
190+ EOF
191+ git add .gitmodules &&
192+ test_tick &&
193+ git commit -m "gitmodules with relative URL that strips off scheme" &&
194+ test_when_finished "rm -rf dst" &&
195+ git init --bare dst &&
196+ git -C dst config transfer.fsckObjects true &&
197+ test_must_fail git push dst HEAD 2>err &&
198+ grep gitmodulesUrl err
199+'
200+
201 test_expect_success 'fsck permits embedded newline with unrecognized scheme' '
202 git checkout --orphan newscheme &&
203 cat >.gitmodules <<-\EOF &&
204--
2051.9.1
206
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-8.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-8.patch
new file mode 100644
index 0000000000..935d47795f
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-8.patch
@@ -0,0 +1,114 @@
1From 5e06d0781a963d62413ae7eab4eb78cc7195af8b Mon Sep 17 00:00:00 2001
2From: Jonathan Nieder <jrnieder@gmail.com>
3Date: Sat, 18 Apr 2020 20:54:57 -0700
4Subject: [PATCH 11/12] credential: treat URL with empty scheme as invalid
5
6Until "credential: refuse to operate when missing host or protocol",
7Git's credential handling code interpreted URLs with empty scheme to
8mean "give me credentials matching this host for any protocol".
9
10Luckily libcurl does not recognize such URLs (it tries to look for a
11protocol named "" and fails). Just in case that changes, let's reject
12them within Git as well. This way, credential_from_url is guaranteed to
13always produce a "struct credential" with protocol and host set.
14
15Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
16
17Upstream-Status: Backport
18CVE: CVE-2020-11008 (8)
19Signed-off-by: Li Zhou <li.zhou@windriver.com>
20---
21 credential.c | 5 ++---
22 t/t5550-http-fetch-dumb.sh | 9 +++++++++
23 t/t7416-submodule-dash-url.sh | 32 ++++++++++++++++++++++++++++++++
24 3 files changed, 43 insertions(+), 3 deletions(-)
25
26diff --git a/credential.c b/credential.c
27index 1e1aed5..cf11cc9 100644
28--- a/credential.c
29+++ b/credential.c
30@@ -360,7 +360,7 @@ int credential_from_url_gently(struct credential *c, const char *url,
31 * (3) proto://<user>:<pass>@<host>/...
32 */
33 proto_end = strstr(url, "://");
34- if (!proto_end) {
35+ if (!proto_end || proto_end == url) {
36 if (!quiet)
37 warning(_("url has no scheme: %s"), url);
38 return -1;
39@@ -385,8 +385,7 @@ int credential_from_url_gently(struct credential *c, const char *url,
40 host = at + 1;
41 }
42
43- if (proto_end - url > 0)
44- c->protocol = xmemdupz(url, proto_end - url);
45+ c->protocol = xmemdupz(url, proto_end - url);
46 c->host = url_decode_mem(host, slash - host);
47 /* Trim leading and trailing slashes from path */
48 while (*slash == '/')
49diff --git a/t/t5550-http-fetch-dumb.sh b/t/t5550-http-fetch-dumb.sh
50index 1c9e5d3..ea2688b 100755
51--- a/t/t5550-http-fetch-dumb.sh
52+++ b/t/t5550-http-fetch-dumb.sh
53@@ -325,6 +325,15 @@ test_expect_success 'remote-http complains cleanly about malformed urls' '
54 test_i18ngrep "url has no scheme" stderr
55 '
56
57+# NEEDSWORK: Writing commands to git-remote-curl can race against the latter
58+# erroring out, producing SIGPIPE. Remove "ok=sigpipe" once transport-helper has
59+# learned to handle early remote helper failures more cleanly.
60+test_expect_success 'remote-http complains cleanly about empty scheme' '
61+ test_must_fail ok=sigpipe git ls-remote \
62+ http::${HTTPD_URL#http}/dumb/repo.git 2>stderr &&
63+ test_i18ngrep "url has no scheme" stderr
64+'
65+
66 test_expect_success 'redirects can be forbidden/allowed' '
67 test_must_fail git -c http.followRedirects=false \
68 clone $HTTPD_URL/dumb-redir/repo.git dumb-redir &&
69diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
70index 249dc3d..9309040 100755
71--- a/t/t7416-submodule-dash-url.sh
72+++ b/t/t7416-submodule-dash-url.sh
73@@ -92,6 +92,38 @@ test_expect_success 'fsck rejects relative URL resolving to missing scheme' '
74 grep gitmodulesUrl err
75 '
76
77+test_expect_success 'fsck rejects empty URL scheme' '
78+ git checkout --orphan empty-scheme &&
79+ cat >.gitmodules <<-\EOF &&
80+ [submodule "foo"]
81+ url = http::://one.example.com/foo.git
82+ EOF
83+ git add .gitmodules &&
84+ test_tick &&
85+ git commit -m "gitmodules with empty URL scheme" &&
86+ test_when_finished "rm -rf dst" &&
87+ git init --bare dst &&
88+ git -C dst config transfer.fsckObjects true &&
89+ test_must_fail git push dst HEAD 2>err &&
90+ grep gitmodulesUrl err
91+'
92+
93+test_expect_success 'fsck rejects relative URL resolving to empty scheme' '
94+ git checkout --orphan relative-empty-scheme &&
95+ cat >.gitmodules <<-\EOF &&
96+ [submodule "foo"]
97+ url = ../../../:://one.example.com/foo.git
98+ EOF
99+ git add .gitmodules &&
100+ test_tick &&
101+ git commit -m "relative gitmodules URL resolving to empty scheme" &&
102+ test_when_finished "rm -rf dst" &&
103+ git init --bare dst &&
104+ git -C dst config transfer.fsckObjects true &&
105+ test_must_fail git push dst HEAD 2>err &&
106+ grep gitmodulesUrl err
107+'
108+
109 test_expect_success 'fsck permits embedded newline with unrecognized scheme' '
110 git checkout --orphan newscheme &&
111 cat >.gitmodules <<-\EOF &&
112--
1131.9.1
114
diff --git a/meta/recipes-devtools/git/git/CVE-2020-11008-9.patch b/meta/recipes-devtools/git/git/CVE-2020-11008-9.patch
new file mode 100644
index 0000000000..22292dbbbf
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-11008-9.patch
@@ -0,0 +1,114 @@
1From 2e084e25fa454c58a600c9434f776f2150037a76 Mon Sep 17 00:00:00 2001
2From: Jonathan Nieder <jrnieder@gmail.com>
3Date: Sat, 18 Apr 2020 20:57:22 -0700
4Subject: [PATCH 12/12] fsck: reject URL with empty host in .gitmodules
5
6Git's URL parser interprets
7
8 https:///example.com/repo.git
9
10to have no host and a path of "example.com/repo.git". Curl, on the
11other hand, internally redirects it to https://example.com/repo.git. As
12a result, until "credential: parse URL without host as empty host, not
13unset", tricking a user into fetching from such a URL would cause Git to
14send credentials for another host to example.com.
15
16Teach fsck to block and detect .gitmodules files using such a URL to
17prevent sharing them with Git versions that are not yet protected.
18
19A relative URL in a .gitmodules file could also be used to trigger this.
20The relative URL resolver used for .gitmodules does not normalize
21sequences of slashes and can follow ".." components out of the path part
22and to the host part of a URL, meaning that such a relative URL can be
23used to traverse from a https://foo.example.com/innocent superproject to
24a https:///attacker.example.com/exploit submodule. Fortunately,
25redundant extra slashes in .gitmodules are rare, so we can catch this by
26detecting one after a leading sequence of "./" and "../" components.
27
28Helped-by: Jeff King <peff@peff.net>
29Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
30Reviewed-by: Jeff King <peff@peff.net>
31
32Upstream-Status: Backport
33CVE: CVE-2020-11008 (9)
34Signed-off-by: Li Zhou <li.zhou@windriver.com>
35---
36 fsck.c | 10 +++++++---
37 t/t7416-submodule-dash-url.sh | 32 ++++++++++++++++++++++++++++++++
38 2 files changed, 39 insertions(+), 3 deletions(-)
39
40diff --git a/fsck.c b/fsck.c
41index 30eac29..00077b1 100644
42--- a/fsck.c
43+++ b/fsck.c
44@@ -1070,17 +1070,21 @@ static int check_submodule_url(const char *url)
45 /*
46 * URLs which escape their root via "../" can overwrite
47 * the host field and previous components, resolving to
48- * URLs like https::example.com/submodule.git that were
49+ * URLs like https::example.com/submodule.git and
50+ * https:///example.com/submodule.git that were
51 * susceptible to CVE-2020-11008.
52 */
53 if (count_leading_dotdots(url, &next) > 0 &&
54- *next == ':')
55+ (*next == ':' || *next == '/'))
56 return -1;
57 }
58
59 else if (url_to_curl_url(url, &curl_url)) {
60 struct credential c = CREDENTIAL_INIT;
61- int ret = credential_from_url_gently(&c, curl_url, 1);
62+ int ret = 0;
63+ if (credential_from_url_gently(&c, curl_url, 1) ||
64+ !*c.host)
65+ ret = -1;
66 credential_clear(&c);
67 return ret;
68 }
69diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh
70index 9309040..eec96e0 100755
71--- a/t/t7416-submodule-dash-url.sh
72+++ b/t/t7416-submodule-dash-url.sh
73@@ -124,6 +124,38 @@ test_expect_success 'fsck rejects relative URL resolving to empty scheme' '
74 grep gitmodulesUrl err
75 '
76
77+test_expect_success 'fsck rejects empty hostname' '
78+ git checkout --orphan empty-host &&
79+ cat >.gitmodules <<-\EOF &&
80+ [submodule "foo"]
81+ url = http:///one.example.com/foo.git
82+ EOF
83+ git add .gitmodules &&
84+ test_tick &&
85+ git commit -m "gitmodules with extra slashes" &&
86+ test_when_finished "rm -rf dst" &&
87+ git init --bare dst &&
88+ git -C dst config transfer.fsckObjects true &&
89+ test_must_fail git push dst HEAD 2>err &&
90+ grep gitmodulesUrl err
91+'
92+
93+test_expect_success 'fsck rejects relative url that produced empty hostname' '
94+ git checkout --orphan messy-relative &&
95+ cat >.gitmodules <<-\EOF &&
96+ [submodule "foo"]
97+ url = ../../..//one.example.com/foo.git
98+ EOF
99+ git add .gitmodules &&
100+ test_tick &&
101+ git commit -m "gitmodules abusing relative_path" &&
102+ test_when_finished "rm -rf dst" &&
103+ git init --bare dst &&
104+ git -C dst config transfer.fsckObjects true &&
105+ test_must_fail git push dst HEAD 2>err &&
106+ grep gitmodulesUrl err
107+'
108+
109 test_expect_success 'fsck permits embedded newline with unrecognized scheme' '
110 git checkout --orphan newscheme &&
111 cat >.gitmodules <<-\EOF &&
112--
1131.9.1
114
diff --git a/meta/recipes-devtools/git/git/CVE-2020-5260.patch b/meta/recipes-devtools/git/git/CVE-2020-5260.patch
new file mode 100644
index 0000000000..d03e701a8f
--- /dev/null
+++ b/meta/recipes-devtools/git/git/CVE-2020-5260.patch
@@ -0,0 +1,65 @@
1From 9a6bbee8006c24b46a85d29e7b38cfa79e9ab21b Mon Sep 17 00:00:00 2001
2From: Jeff King <peff@peff.net>
3Date: Wed, 11 Mar 2020 17:53:41 -0400
4Subject: [PATCH] credential: avoid writing values with newlines
5
6The credential protocol that we use to speak to helpers can't represent
7values with newlines in them. This was an intentional design choice to
8keep the protocol simple, since none of the values we pass should
9generally have newlines.
10
11However, if we _do_ encounter a newline in a value, we blindly transmit
12it in credential_write(). Such values may break the protocol syntax, or
13worse, inject new valid lines into the protocol stream.
14
15The most likely way for a newline to end up in a credential struct is by
16decoding a URL with a percent-encoded newline. However, since the bug
17occurs at the moment we write the value to the protocol, we'll catch it
18there. That should leave no possibility of accidentally missing a code
19path that can trigger the problem.
20
21At this level of the code we have little choice but to die(). However,
22since we'd not ever expect to see this case outside of a malicious URL,
23that's an acceptable outcome.
24
25Reported-by: Felix Wilhelm <fwilhelm@google.com>
26
27Upstream-Status: Backport
28CVE: CVE-2020-5260
29Signed-off-by: Li Zhou <li.zhou@windriver.com>
30---
31 credential.c | 2 ++
32 t/t0300-credentials.sh | 6 ++++++
33 2 files changed, 8 insertions(+)
34
35diff --git a/credential.c b/credential.c
36index 9747f47..00ee4d6 100644
37--- a/credential.c
38+++ b/credential.c
39@@ -194,6 +194,8 @@ static void credential_write_item(FILE *fp, const char *key, const char *value)
40 {
41 if (!value)
42 return;
43+ if (strchr(value, '\n'))
44+ die("credential value for %s contains newline", key);
45 fprintf(fp, "%s=%s\n", key, value);
46 }
47
48diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
49index 03bd31e..15cc3c5 100755
50--- a/t/t0300-credentials.sh
51+++ b/t/t0300-credentials.sh
52@@ -309,4 +309,10 @@ test_expect_success 'empty helper spec resets helper list' '
53 EOF
54 '
55
56+test_expect_success 'url parser rejects embedded newlines' '
57+ test_must_fail git credential fill <<-\EOF
58+ url=https://one.example.com?%0ahost=two.example.com/
59+ EOF
60+'
61+
62 test_done
63--
641.9.1
65