From 9cc7c20d1580763deae28dee5c017769ace8681a Mon Sep 17 00:00:00 2001 From: yang_zhuang_zhuang <1162011203@qq.com> Date: Tue, 28 Jul 2020 14:14:42 +0800 Subject: [PATCH] update version to 2.27.0 --- CVE-2019-1348.patch | 259 ---------------- CVE-2019-1349.patch | 237 --------------- CVE-2019-1350.patch | 99 ------ CVE-2019-1351.patch | 135 --------- CVE-2019-1352.patch | 94 ------ CVE-2019-1353.patch | 142 --------- CVE-2019-1354.patch | 105 ------- CVE-2019-1387.patch | 181 ----------- CVE-2019-19604.patch | 148 --------- CVE-2020-11008-1.patch | 63 ---- CVE-2020-11008-2.patch | 285 ------------------ CVE-2020-11008-3.patch | 86 ------ CVE-2020-11008-4.patch | 164 ---------- CVE-2020-11008-5.patch | 205 ------------- CVE-2020-11008-6.patch | 75 ----- CVE-2020-11008-7.patch | 194 ------------ CVE-2020-11008-8.patch | 104 ------- CVE-2020-11008-9.patch | 106 ------- CVE-2020-5260.patch | 61 ---- ...t-unrepresentable-values-when-parsin.patch | 151 ---------- ...y-creating-leading-directories-for-e.patch | 88 ------ ...-creating-leading-directories-for-im.patch | 40 --- ...ten-parsing-of-boolean-command-line-.patch | 39 --- ...tmodules-URLs-with-embedded-newlines.patch | 99 ------ git-2.23.0.tar.sign | Bin 566 -> 0 bytes git-2.27.0.tar.sign | Bin 0 -> 566 bytes git-2.23.0.tar.xz => git-2.27.0.tar.xz | Bin 5707148 -> 6074636 bytes git.spec | 41 +-- ...cument-the-purpose-of-is_ntfs_dotgit.patch | 56 ---- skip-updating-the-preference.patch | 26 -- t9300-drop-some-useless-uses-of-cat.patch | 61 ---- 31 files changed, 9 insertions(+), 3335 deletions(-) delete mode 100644 CVE-2019-1348.patch delete mode 100644 CVE-2019-1349.patch delete mode 100644 CVE-2019-1350.patch delete mode 100644 CVE-2019-1351.patch delete mode 100644 CVE-2019-1352.patch delete mode 100644 CVE-2019-1353.patch delete mode 100644 CVE-2019-1354.patch delete mode 100644 CVE-2019-1387.patch delete mode 100644 CVE-2019-19604.patch delete mode 100644 CVE-2020-11008-1.patch delete mode 100644 CVE-2020-11008-2.patch delete mode 100644 CVE-2020-11008-3.patch delete mode 100644 CVE-2020-11008-4.patch delete mode 100644 CVE-2020-11008-5.patch delete mode 100644 CVE-2020-11008-6.patch delete mode 100644 CVE-2020-11008-7.patch delete mode 100644 CVE-2020-11008-8.patch delete mode 100644 CVE-2020-11008-9.patch delete mode 100644 CVE-2020-5260.patch delete mode 100644 credential-detect-unrepresentable-values-when-parsin.patch delete mode 100644 fast-import-delay-creating-leading-directories-for-e.patch delete mode 100644 fast-import-stop-creating-leading-directories-for-im.patch delete mode 100644 fast-import-tighten-parsing-of-boolean-command-line-.patch delete mode 100644 fsck-detect-gitmodules-URLs-with-embedded-newlines.patch delete mode 100644 git-2.23.0.tar.sign create mode 100644 git-2.27.0.tar.sign rename git-2.23.0.tar.xz => git-2.27.0.tar.xz (42%) delete mode 100644 path.c-document-the-purpose-of-is_ntfs_dotgit.patch delete mode 100644 skip-updating-the-preference.patch delete mode 100644 t9300-drop-some-useless-uses-of-cat.patch diff --git a/CVE-2019-1348.patch b/CVE-2019-1348.patch deleted file mode 100644 index e1d9007..0000000 --- a/CVE-2019-1348.patch +++ /dev/null @@ -1,259 +0,0 @@ -From 68061e3470210703cb15594194718d35094afdc0 Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Thu, 29 Aug 2019 14:37:26 -0400 -Subject: [PATCH] fast-import: disallow "feature export-marks" by default - -The fast-import stream command "feature export-marks=" lets the -stream write marks to an arbitrary path. This may be surprising if you -are running fast-import against an untrusted input (which otherwise -cannot do anything except update Git objects and refs). - -Let's disallow the use of this feature by default, and provide a -command-line option to re-enable it (you can always just use the -command-line --export-marks as well, but the in-stream version provides -an easy way for exporters to control the process). - -This is a backwards-incompatible change, since the default is flipping -to the new, safer behavior. However, since the main users of the -in-stream versions would be import/export-based remote helpers, and -since we trust remote helpers already (which are already running -arbitrary code), we'll pass the new option by default when reading a -remote helper's stream. This should minimize the impact. - -Note that the implementation isn't totally simple, as we have to work -around the fact that fast-import doesn't parse its command-line options -until after it has read any "feature" lines from the stream. This is how -it lets command-line options override in-stream. But in our case, it's -important to parse the new --allow-unsafe-features first. - -There are three options for resolving this: - - 1. Do a separate "early" pass over the options. This is easy for us to - do because there are no command-line options that allow the - "unstuck" form (so there's no chance of us mistaking an argument - for an option), though it does introduce a risk of incorrect - parsing later (e.g,. if we convert to parse-options). - - 2. Move the option parsing phase back to the start of the program, but - teach the stream-reading code never to override an existing value. - This is tricky, because stream "feature" lines override each other - (meaning we'd have to start tracking the source for every option). - - 3. Accept that we might parse a "feature export-marks" line that is - forbidden, as long we don't _act_ on it until after we've parsed - the command line options. - - This would, in fact, work with the current code, but only because - the previous patch fixed the export-marks parser to avoid touching - the filesystem. - - So while it works, it does carry risk of somebody getting it wrong - in the future in a rather subtle and unsafe way. - -I've gone with option (1) here as simple, safe, and unlikely to cause -regressions. - -This fixes CVE-2019-1348. - -Signed-off-by: Jeff King ---- - Documentation/git-fast-import.txt | 14 ++++++++++++++ - fast-import.c | 25 +++++++++++++++++++++++++ - t/t9300-fast-import.sh | 23 +++++++++++++++-------- - transport-helper.c | 1 + - 4 files changed, 55 insertions(+), 8 deletions(-) - -diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt -index fad327a..76747ef 100644 ---- a/Documentation/git-fast-import.txt -+++ b/Documentation/git-fast-import.txt -@@ -51,6 +51,20 @@ OPTIONS - memory used by fast-import during this run. Showing this output - is currently the default, but can be disabled with --quiet. - -+--allow-unsafe-features:: -+ Many command-line options can be provided as part of the -+ fast-import stream itself by using the `feature` or `option` -+ commands. However, some of these options are unsafe (e.g., -+ allowing fast-import to access the filesystem outside of the -+ repository). These options are disabled by default, but can be -+ allowed by providing this option on the command line. This -+ currently impacts only the `feature export-marks` command. -++ -+ Only enable this option if you trust the program generating the -+ fast-import stream! This option is enabled automatically for -+ remote-helpers that use the `import` capability, as they are -+ already trusted to run their own code. -+ - Options for Frontends - ~~~~~~~~~~~~~~~~~~~~~ - -diff --git a/fast-import.c b/fast-import.c -index 71312d4..b001abc 100644 ---- a/fast-import.c -+++ b/fast-import.c -@@ -217,6 +217,7 @@ struct recent_command { - static struct strbuf new_data = STRBUF_INIT; - static int seen_data_command; - static int require_explicit_termination; -+static int allow_unsafe_features; - - /* Signal handling */ - static volatile sig_atomic_t checkpoint_requested; -@@ -3171,6 +3172,8 @@ static int parse_one_option(const char *option) - show_stats = 0; - } else if (!strcmp(option, "stats")) { - show_stats = 1; -+ } else if (!strcmp(option, "allow-unsafe-features")) { -+ ; /* already handled during early option parsing */ - } else { - return 0; - } -@@ -3178,6 +3181,13 @@ static int parse_one_option(const char *option) - return 1; - } - -+static void check_unsafe_feature(const char *feature, int from_stream) -+{ -+ if (from_stream && !allow_unsafe_features) -+ die(_("feature '%s' forbidden in input without --allow-unsafe-features"), -+ feature); -+} -+ - static int parse_one_feature(const char *feature, int from_stream) - { - const char *arg; -@@ -3189,6 +3199,7 @@ static int parse_one_feature(const char *feature, int from_stream) - } else if (skip_prefix(feature, "import-marks-if-exists=", &arg)) { - option_import_marks(arg, from_stream, 1); - } else if (skip_prefix(feature, "export-marks=", &arg)) { -+ check_unsafe_feature(feature, from_stream); - option_export_marks(arg); - } else if (!strcmp(feature, "get-mark")) { - ; /* Don't die - this feature is supported */ -@@ -3315,6 +3326,20 @@ int cmd_main(int argc, const char **argv) - avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*)); - marks = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set)); - -+ /* -+ * We don't parse most options until after we've seen the set of -+ * "feature" lines at the start of the stream (which allows the command -+ * line to override stream data). But we must do an early parse of any -+ * command-line options that impact how we interpret the feature lines. -+ */ -+ for (i = 1; i < argc; i++) { -+ const char *arg = argv[i]; -+ if (*arg != '-' || !strcmp(arg, "--")) -+ break; -+ if (!strcmp(arg, "--allow-unsafe-features")) -+ allow_unsafe_features = 1; -+ } -+ - global_argc = argc; - global_argv = argv; - -diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh -index 913ff89..8ca58f5 100755 ---- a/t/t9300-fast-import.sh -+++ b/t/t9300-fast-import.sh -@@ -2115,6 +2115,11 @@ test_expect_success 'R: only one import-marks feature allowed per stream' ' - test_must_fail git fast-import input && -+ test_must_fail git fast-import input <<-EOF && - feature export-marks=git.marks -@@ -2125,7 +2130,7 @@ test_expect_success 'R: export-marks feature results in a marks file being creat - - EOF - -- git fast-import one.marks && - tail -n +3 marks.out > two.marks && -- git fast-import --import-marks=one.marks --import-marks=two.marks in = xdup(helper->out); - argv_array_push(&fastimport->args, "fast-import"); -+ argv_array_push(&fastimport->args, "--allow-unsafe-features"); - argv_array_push(&fastimport->args, debug ? "--stats" : "--quiet"); - - if (data->bidi_import) { --- -1.8.3.1 - diff --git a/CVE-2019-1349.patch b/CVE-2019-1349.patch deleted file mode 100644 index 5e5f355..0000000 --- a/CVE-2019-1349.patch +++ /dev/null @@ -1,237 +0,0 @@ -From 629226a8902640470bb8cf9521f058340e7c0248 Mon Sep 17 00:00:00 2001 -From: Johannes Schindelin -Date: Thu, 12 Sep 2019 14:20:39 +0200 -Subject: [PATCH 07/30] clone --recurse-submodules: prevent name squatting on - Windows - -In addition to preventing `.git` from being tracked by Git, on Windows -we also have to prevent `git~1` from being tracked, as the default NTFS -short name (also known as the "8.3 filename") for the file name `.git` -is `git~1`, otherwise it would be possible for malicious repositories to -write directly into the `.git/` directory, e.g. a `post-checkout` hook -that would then be executed _during_ a recursive clone. - -When we implemented appropriate protections in 2b4c6efc821 (read-cache: -optionally disallow NTFS .git variants, 2014-12-16), we had analyzed -carefully that the `.git` directory or file would be guaranteed to be -the first directory entry to be written. Otherwise it would be possible -e.g. for a file named `..git` to be assigned the short name `git~1` and -subsequently, the short name generated for `.git` would be `git~2`. Or -`git~3`. Or even `~9999999` (for a detailed explanation of the lengths -we have to go to protect `.gitmodules`, see the commit message of -e7cb0b4455c (is_ntfs_dotgit: match other .git files, 2018-05-11)). - -However, by exploiting two issues (that will be addressed in a related -patch series close by), it is currently possible to clone a submodule -into a non-empty directory: - -- On Windows, file names cannot end in a space or a period (for - historical reasons: the period separating the base name from the file - extension was not actually written to disk, and the base name/file - extension was space-padded to the full 8/3 characters, respectively). - Helpfully, when creating a directory under the name, say, `sub.`, that - trailing period is trimmed automatically and the actual name on disk - is `sub`. - - This means that while Git thinks that the submodule names `sub` and - `sub.` are different, they both access `.git/modules/sub/`. - -- While the backslash character is a valid file name character on Linux, - it is not so on Windows. As Git tries to be cross-platform, it - therefore allows backslash characters in the file names stored in tree - objects. - - Which means that it is totally possible that a submodule `c` sits next - to a file `c\..git`, and on Windows, during recursive clone a file - called `..git` will be written into `c/`, of course _before_ the - submodule is cloned. - -Note that the actual exploit is not quite as simple as having a -submodule `c` next to a file `c\..git`, as we have to make sure that the -directory `.git/modules/b` already exists when the submodule is checked -out, otherwise a different code path is taken in `module_clone()` that -does _not_ allow a non-empty submodule directory to exist already. - -Even if we will address both issues nearby (the next commit will -disallow backslash characters in tree entries' file names on Windows, -and another patch will disallow creating directories/files with trailing -spaces or periods), it is a wise idea to defend in depth against this -sort of attack vector: when submodules are cloned recursively, we now -_require_ the directory to be empty, addressing CVE-2019-1349. - -Note: the code path we patch is shared with the code path of `git -submodule update --init`, which must not expect, in general, that the -directory is empty. Hence we have to introduce the new option -`--force-init` and hand it all the way down from `git submodule` to the -actual `git submodule--helper` process that performs the initial clone. - -Reported-by: Nicolas Joly -Signed-off-by: Johannes Schindelin ---- - builtin/clone.c | 2 +- - builtin/submodule--helper.c | 14 ++++++++++++-- - git-submodule.sh | 6 ++++++ - t/t7415-submodule-names.sh | 31 +++++++++++++++++++++++++++++++ - 4 files changed, 50 insertions(+), 3 deletions(-) - -diff --git a/builtin/clone.c b/builtin/clone.c -index f665b28..e48476d 100644 ---- a/builtin/clone.c -+++ b/builtin/clone.c -@@ -790,7 +790,7 @@ static int checkout(int submodule_progress) - - if (!err && (option_recurse_submodules.nr > 0)) { - struct argv_array args = ARGV_ARRAY_INIT; -- argv_array_pushl(&args, "submodule", "update", "--init", "--recursive", NULL); -+ argv_array_pushl(&args, "submodule", "update", "--require-init", "--recursive", NULL); - - if (option_shallow_submodules == 1) - argv_array_push(&args, "--depth=1"); -diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c -index 909e77e..f3ba6aa 100644 ---- a/builtin/submodule--helper.c -+++ b/builtin/submodule--helper.c -@@ -19,6 +19,7 @@ - #include "diffcore.h" - #include "diff.h" - #include "object-store.h" -+#include "dir.h" - - #define OPT_QUIET (1 << 0) - #define OPT_CACHED (1 << 1) -@@ -1359,7 +1360,7 @@ static int module_clone(int argc, const char **argv, const char *prefix) - char *p, *path = NULL, *sm_gitdir; - struct strbuf sb = STRBUF_INIT; - struct string_list reference = STRING_LIST_INIT_NODUP; -- int dissociate = 0; -+ int dissociate = 0, require_init = 0; - char *sm_alternate = NULL, *error_strategy = NULL; - - struct option module_clone_options[] = { -@@ -1386,6 +1387,8 @@ static int module_clone(int argc, const char **argv, const char *prefix) - OPT__QUIET(&quiet, "Suppress output for cloning a submodule"), - OPT_BOOL(0, "progress", &progress, - N_("force cloning progress")), -+ OPT_BOOL(0, "require-init", &require_init, -+ N_("disallow cloning into non-empty directory")), - OPT_END() - }; - -@@ -1424,6 +1427,8 @@ static int module_clone(int argc, const char **argv, const char *prefix) - die(_("clone of '%s' into submodule path '%s' failed"), - url, path); - } else { -+ if (require_init && !access(path, X_OK) && !is_empty_dir(path)) -+ die(_("directory not empty: '%s'"), path); - if (safe_create_leading_directories_const(path) < 0) - die(_("could not create directory '%s'"), path); - strbuf_addf(&sb, "%s/index", sm_gitdir); -@@ -1536,6 +1541,7 @@ struct submodule_update_clone { - int recommend_shallow; - struct string_list references; - int dissociate; -+ unsigned require_init; - const char *depth; - const char *recursive_prefix; - const char *prefix; -@@ -1554,7 +1560,7 @@ struct submodule_update_clone { - int max_jobs; - }; - #define SUBMODULE_UPDATE_CLONE_INIT {0, MODULE_LIST_INIT, 0, \ -- SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, \ -+ SUBMODULE_UPDATE_STRATEGY_INIT, 0, 0, -1, STRING_LIST_INIT_DUP, 0, 0, \ - NULL, NULL, NULL, \ - NULL, 0, 0, 0, NULL, 0, 0, 1} - -@@ -1681,6 +1687,8 @@ static int prepare_to_clone_next_submodule(const struct cache_entry *ce, - argv_array_pushl(&child->args, "--prefix", suc->prefix, NULL); - if (suc->recommend_shallow && sub->recommend_shallow == 1) - argv_array_push(&child->args, "--depth=1"); -+ if (suc->require_init) -+ argv_array_push(&child->args, "--require-init"); - argv_array_pushl(&child->args, "--path", sub->path, NULL); - argv_array_pushl(&child->args, "--name", sub->name, NULL); - argv_array_pushl(&child->args, "--url", url, NULL); -@@ -1870,6 +1878,8 @@ static int update_clone(int argc, const char **argv, const char *prefix) - OPT__QUIET(&suc.quiet, N_("don't print cloning progress")), - OPT_BOOL(0, "progress", &suc.progress, - N_("force cloning progress")), -+ OPT_BOOL(0, "require-init", &suc.require_init, -+ N_("disallow cloning into non-empty directory")), - OPT_END() - }; - -diff --git a/git-submodule.sh b/git-submodule.sh -index c7f58c5..58713c5 100755 ---- a/git-submodule.sh -+++ b/git-submodule.sh -@@ -36,6 +36,7 @@ reference= - cached= - recursive= - init= -+require_init= - files= - remote= - nofetch= -@@ -466,6 +467,10 @@ cmd_update() - -i|--init) - init=1 - ;; -+ --require-init) -+ init=1 -+ require_init=1 -+ ;; - --remote) - remote=1 - ;; -@@ -548,6 +553,7 @@ cmd_update() - ${reference:+"$reference"} \ - ${dissociate:+"--dissociate"} \ - ${depth:+--depth "$depth"} \ -+ ${require_init:+--require-init} \ - $recommend_shallow \ - $jobs \ - -- \ -diff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh -index 49a37ef..75dcdff 100755 ---- a/t/t7415-submodule-names.sh -+++ b/t/t7415-submodule-names.sh -@@ -191,4 +191,35 @@ test_expect_success 'fsck detects corrupt .gitmodules' ' - ) - ' - -+test_expect_success MINGW 'prevent git~1 squatting on Windows' ' -+ git init squatting && -+ ( -+ cd squatting && -+ mkdir a && -+ touch a/..git && -+ git add a/..git && -+ test_tick && -+ git commit -m initial && -+ -+ modules="$(test_write_lines \ -+ "[submodule \"b.\"]" "url = ." "path = c" \ -+ "[submodule \"b\"]" "url = ." "path = d\\\\a" | -+ git hash-object -w --stdin)" && -+ rev="$(git rev-parse --verify HEAD)" && -+ hash="$(echo x | git hash-object -w --stdin)" && -+ git update-index --add \ -+ --cacheinfo 100644,$modules,.gitmodules \ -+ --cacheinfo 160000,$rev,c \ -+ --cacheinfo 160000,$rev,d\\a \ -+ --cacheinfo 100644,$hash,d./a/x \ -+ --cacheinfo 100644,$hash,d./a/..git && -+ test_tick && -+ git commit -m "module" -+ ) && -+ test_must_fail git \ -+ clone --recurse-submodules squatting squatting-clone 2>err && -+ test_i18ngrep "directory not empty" err && -+ ! grep gitdir squatting-clone/d/a/git~2 -+' -+ - test_done --- -1.8.3.1 - diff --git a/CVE-2019-1350.patch b/CVE-2019-1350.patch deleted file mode 100644 index dccb4f8..0000000 --- a/CVE-2019-1350.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 6d8684161ee9c03bed5cb69ae76dfdddb85a0003 Mon Sep 17 00:00:00 2001 -From: Johannes Schindelin -Date: Fri, 13 Sep 2019 16:32:43 +0200 -Subject: [PATCH] mingw: fix quoting of arguments - -We need to be careful to follow proper quoting rules. For example, if an -argument contains spaces, we have to quote them. Double-quotes need to -be escaped. Backslashes need to be escaped, but only if they are -followed by a double-quote character. - -We need to be _extra_ careful to consider the case where an argument -ends in a backslash _and_ needs to be quoted: in this case, we append a -double-quote character, i.e. the backslash now has to be escaped! - -The current code, however, fails to recognize that, and therefore can -turn an argument that ends in a single backslash into a quoted argument -that now ends in an escaped double-quote character. This allows -subsequent command-line parameters to be split and part of them being -mistaken for command-line options, e.g. through a maliciously-crafted -submodule URL during a recursive clone. - - -Technically, we would not need to quote _all_ arguments which end in a -backslash _unless_ the argument needs to be quoted anyway. For example, -`test\` would not need to be quoted, while `test \` would need to be. - -To keep the code simple, however, and therefore easier to reason about -and ensure its correctness, we now _always_ quote an argument that ends -in a backslash. - -This addresses CVE-2019-1350. - -Signed-off-by: Johannes Schindelin ---- - compat/mingw.c | 9 ++++++--- - t/t7416-submodule-dash-url.sh | 14 ++++++++++++++ - 2 files changed, 20 insertions(+), 3 deletions(-) - -diff --git a/compat/mingw.c b/compat/mingw.c -index 738f0a8..48cdf83 100644 ---- a/compat/mingw.c -+++ b/compat/mingw.c -@@ -1052,7 +1052,7 @@ static const char *quote_arg_msvc(const char *arg) - p++; - len++; - } -- if (*p == '"') -+ if (*p == '"' || !*p) - n += count*2 + 1; - continue; - } -@@ -1074,16 +1074,19 @@ static const char *quote_arg_msvc(const char *arg) - count++; - *d++ = *arg++; - } -- if (*arg == '"') { -+ if (*arg == '"' || !*arg) { - while (count-- > 0) - *d++ = '\\'; -+ /* don't escape the surrounding end quote */ -+ if (!*arg) -+ break; - *d++ = '\\'; - } - } - *d++ = *arg++; - } - *d++ = '"'; -- *d++ = 0; -+ *d++ = '\0'; - return q; - } - -diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh -index 1cd2c1c..5ba041f 100755 ---- a/t/t7416-submodule-dash-url.sh -+++ b/t/t7416-submodule-dash-url.sh -@@ -46,4 +46,18 @@ test_expect_success 'fsck rejects unprotected dash' ' - grep gitmodulesUrl err - ' - -+test_expect_success 'trailing backslash is handled correctly' ' -+ git init testmodule && -+ test_commit -C testmodule c && -+ git submodule add ./testmodule && -+ : ensure that the name ends in a double backslash && -+ sed -e "s|\\(submodule \"testmodule\\)\"|\\1\\\\\\\\\"|" \ -+ -e "s|url = .*|url = \" --should-not-be-an-option\"|" \ -+ <.gitmodules >.new && -+ mv .new .gitmodules && -+ git commit -am "Add testmodule" && -+ test_must_fail git clone --verbose --recurse-submodules . dolly 2>err && -+ test_i18ngrep ! "unknown option" err -+' -+ - test_done --- -1.8.3.1 - diff --git a/CVE-2019-1351.patch b/CVE-2019-1351.patch deleted file mode 100644 index 08eac8d..0000000 --- a/CVE-2019-1351.patch +++ /dev/null @@ -1,135 +0,0 @@ -From a94971b023f4583ea4b2c9c9f7a71d53f9781d58 Mon Sep 17 00:00:00 2001 -From: Johannes Schindelin -Date: Fri, 6 Sep 2019 00:09:10 +0200 -Subject: [PATCH] mingw: handle `subst`-ed "DOS drives" -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Over a decade ago, in 25fe217b86c (Windows: Treat Windows style path -names., 2008-03-05), Git was taught to handle absolute Windows paths, -i.e. paths that start with a drive letter and a colon. - -Unbeknownst to us, while drive letters of physical drives are limited to -letters of the English alphabet, there is a way to assign virtual drive -letters to arbitrary directories, via the `subst` command, which is -_not_ limited to English letters. - -It is therefore possible to have absolute Windows paths of the form -`1:\what\the\hex.txt`. Even "better": pretty much arbitrary Unicode -letters can also be used, e.g. `ä:\tschibät.sch`. - -While it can be sensibly argued that users who set up such funny drive -letters really seek adverse consequences, the Windows Operating System -is known to be a platform where many users are at the mercy of -administrators who have their very own idea of what constitutes a -reasonable setup. - -Therefore, let's just make sure that such funny paths are still -considered absolute paths by Git, on Windows. - -In addition to Unicode characters, pretty much any character is a valid -drive letter, as far as `subst` is concerned, even `:` and `"` or even a -space character. While it is probably the opposite of smart to use them, -let's safeguard `is_dos_drive_prefix()` against all of them. - -Note: `[::1]:repo` is a valid URL, but not a valid path on Windows. -As `[` is now considered a valid drive letter, we need to be very -careful to avoid misinterpreting such a string as valid local path in -`url_is_local_not_ssh()`. To do that, we use the just-introduced -function `is_valid_path()` (which will label the string as invalid file -name because of the colon characters). - -This fixes CVE-2019-1351. - -Reported-by: Nicolas Joly -Signed-off-by: Johannes Schindelin ---- - compat/win32/path-utils.c | 24 ++++++++++++++++++++++++ - compat/win32/path-utils.h | 4 ++-- - connect.c | 2 +- - t/t0060-path-utils.sh | 9 +++++++++ - 4 files changed, 36 insertions(+), 3 deletions(-) - -diff --git a/compat/win32/path-utils.c b/compat/win32/path-utils.c -index d9d3641de8..70352af283 100644 ---- a/compat/win32/path-utils.c -+++ b/compat/win32/path-utils.c -@@ -1,5 +1,29 @@ - #include "../../git-compat-util.h" - -+int mingw_has_dos_drive_prefix(const char *path) -+{ -+ int i; -+ -+ /* -+ * Does it start with an ASCII letter (i.e. highest bit not set), -+ * followed by a colon? -+ */ -+ if (!(0x80 & (unsigned char)*path)) -+ return *path && path[1] == ':' ? 2 : 0; -+ -+ /* -+ * While drive letters must be letters of the English alphabet, it is -+ * possible to assign virtually _any_ Unicode character via `subst` as -+ * a drive letter to "virtual drives". Even `1`, or `ä`. Or fun stuff -+ * like this: -+ * -+ * subst ֍: %USERPROFILE%\Desktop -+ */ -+ for (i = 1; i < 4 && (0x80 & (unsigned char)path[i]); i++) -+ ; /* skip first UTF-8 character */ -+ return path[i] == ':' ? i + 1 : 0; -+} -+ - int win32_skip_dos_drive_prefix(char **path) - { - int ret = has_dos_drive_prefix(*path); -diff --git a/compat/win32/path-utils.h b/compat/win32/path-utils.h -index 0f70d43920..22b0c63349 100644 ---- a/compat/win32/path-utils.h -+++ b/compat/win32/path-utils.h -@@ -1,5 +1,5 @@ --#define has_dos_drive_prefix(path) \ -- (isalpha(*(path)) && (path)[1] == ':' ? 2 : 0) -+int mingw_has_dos_drive_prefix(const char *path); -+#define has_dos_drive_prefix mingw_has_dos_drive_prefix - int win32_skip_dos_drive_prefix(char **path); - #define skip_dos_drive_prefix win32_skip_dos_drive_prefix - static inline int win32_is_dir_sep(int c) -diff --git a/connect.c b/connect.c -index 2778481264..4050a797bf 100644 ---- a/connect.c -+++ b/connect.c -@@ -511,7 +511,7 @@ int url_is_local_not_ssh(const char *url) - const char *colon = strchr(url, ':'); - const char *slash = strchr(url, '/'); - return !colon || (slash && slash < colon) || -- has_dos_drive_prefix(url); -+ (has_dos_drive_prefix(url) && is_valid_path(url)); - } - - static const char *prot_name(enum protocol protocol) -diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh -index c7b53e494b..e9b61efdff 100755 ---- a/t/t0060-path-utils.sh -+++ b/t/t0060-path-utils.sh -@@ -165,6 +165,15 @@ test_expect_success 'absolute path rejects the empty string' ' - test_must_fail test-tool path-utils absolute_path "" - ' - -+test_expect_success MINGW ':\\abc is an absolute path' ' -+ for letter in : \" C Z 1 ä -+ do -+ path=$letter:\\abc && -+ absolute="$(test-path-utils absolute_path "$path")" && -+ test "$path" = "$absolute" || return 1 -+ done -+' -+ - test_expect_success 'real path rejects the empty string' ' - test_must_fail test-tool path-utils real_path "" - ' --- -2.23.0 - diff --git a/CVE-2019-1352.patch b/CVE-2019-1352.patch deleted file mode 100644 index a722068..0000000 --- a/CVE-2019-1352.patch +++ /dev/null @@ -1,94 +0,0 @@ -From 7c3745fc6185495d5765628b4dfe1bd2c25a2981 Mon Sep 17 00:00:00 2001 -From: Johannes Schindelin -Date: Wed, 28 Aug 2019 12:22:17 +0200 -Subject: [PATCH] path: safeguard `.git` against NTFS Alternate Streams - Accesses - -Probably inspired by HFS' resource streams, NTFS supports "Alternate -Data Streams": by appending `:` to the file name, -information in addition to the file contents can be written and read, -information that is copied together with the file (unless copied to a -non-NTFS location). - -These Alternate Data Streams are typically used for things like marking -an executable as having just been downloaded from the internet (and -hence not necessarily being trustworthy). - -In addition to a stream name, a stream type can be appended, like so: -`::`. Unless specified, the default stream -type is `$DATA` for files and `$INDEX_ALLOCATION` for directories. In -other words, `.git::$INDEX_ALLOCATION` is a valid way to reference the -`.git` directory! - -In our work in Git v2.2.1 to protect Git on NTFS drives under -`core.protectNTFS`, we focused exclusively on NTFS short names, unaware -of the fact that NTFS Alternate Data Streams offer a similar attack -vector. - -Let's fix this. - -Seeing as it is better to be safe than sorry, we simply disallow paths -referring to *any* NTFS Alternate Data Stream of `.git`, not just -`::$INDEX_ALLOCATION`. This also simplifies the implementation. - -This closes CVE-2019-1352. - -Further reading about NTFS Alternate Data Streams: -https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/c54dec26-1551-4d3a-a0ea-4fa40f848eb3 - -Reported-by: Nicolas Joly -Signed-off-by: Johannes Schindelin ---- - path.c | 12 +++++++++++- - t/t1014-read-tree-confusing.sh | 1 + - 2 files changed, 12 insertions(+), 1 deletion(-) - -diff --git a/path.c b/path.c -index f62a37d..e39ecf4 100644 ---- a/path.c -+++ b/path.c -@@ -1321,10 +1321,19 @@ static int only_spaces_and_periods(const char *path, size_t len, size_t skip) - * `.git` is the first item in a directory, therefore it will be associated - * with the short name `git~1` (unless short names are disabled). - * -+ * - For yet other historical reasons, NTFS supports so-called "Alternate Data -+ * Streams", i.e. metadata associated with a given file, referred to via -+ * `::`. There exists a default stream -+ * type for directories, allowing `.git/` to be accessed via -+ * `.git::$INDEX_ALLOCATION/`. -+ * - * When this function returns 1, it indicates that the specified file/directory - * name refers to a `.git` file or directory, or to any of these synonyms, and - * Git should therefore not track it. - * -+ * For performance reasons, _all_ Alternate Data Streams of `.git/` are -+ * forbidden, not just `::$INDEX_ALLOCATION`. -+ * - * This function is intended to be used by `git fsck` even on platforms where - * the backslash is a regular filename character, therefore it needs to handle - * backlash characters in the provided `name` specially: they are interpreted -@@ -1335,7 +1344,8 @@ int is_ntfs_dotgit(const char *name) - size_t len; - - for (len = 0; ; len++) -- if (!name[len] || name[len] == '\\' || is_dir_sep(name[len])) { -+ if (!name[len] || name[len] == '\\' || is_dir_sep(name[len]) || -+ name[len] == ':') { - if (only_spaces_and_periods(name, len, 4) && - !strncasecmp(name, ".git", 4)) - return 1; -diff --git a/t/t1014-read-tree-confusing.sh b/t/t1014-read-tree-confusing.sh -index 2f5a25d..da3376b 100755 ---- a/t/t1014-read-tree-confusing.sh -+++ b/t/t1014-read-tree-confusing.sh -@@ -49,6 +49,7 @@ git~1 - .git.SPACE .git.{space} - .\\\\.GIT\\\\foobar backslashes - .git\\\\foobar backslashes2 -+.git...:alternate-stream - EOF - - test_expect_success 'utf-8 paths allowed with core.protectHFS off' ' --- -1.8.3.1 - diff --git a/CVE-2019-1353.patch b/CVE-2019-1353.patch deleted file mode 100644 index 53e7d50..0000000 --- a/CVE-2019-1353.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 9102f958ee5254b10c0be72672aa3305bf4f4704 Mon Sep 17 00:00:00 2001 -From: Johannes Schindelin -Date: Mon, 9 Sep 2019 21:04:41 +0200 -Subject: [PATCH] protect_ntfs: turn on NTFS protection by default - -Back in the DOS days, in the FAT file system, file names always -consisted of a base name of length 8 plus a file extension of length 3. -Shorter file names were simply padded with spaces to the full 8.3 -format. - -Later, the FAT file system was taught to support _also_ longer names, -with an 8.3 "short name" as primary file name. While at it, the same -facility allowed formerly illegal file names, such as `.git` (empty base -names were not allowed), which would have the "short name" `git~1` -associated with it. - -For backwards-compatibility, NTFS supports alternative 8.3 short -filenames, too, even if starting with Windows Vista, they are only -generated on the system drive by default. - -We addressed the problem that the `.git/` directory can _also_ be -accessed via `git~1/` (when short names are enabled) in 2b4c6efc821 -(read-cache: optionally disallow NTFS .git variants, 2014-12-16), i.e. -since Git v1.9.5, by introducing the config setting `core.protectNTFS` -and enabling it by default on Windows. - -In the meantime, Windows 10 introduced the "Windows Subsystem for Linux" -(short: WSL), i.e. a way to run Linux applications/distributions in a -thinly-isolated subsystem on Windows (giving rise to many a "2016 is the -Year of Linux on the Desktop" jokes). WSL is getting increasingly -popular, also due to the painless way Linux application can operate -directly ("natively") on files on Windows' file system: the Windows -drives are mounted automatically (e.g. `C:` as `/mnt/c/`). - -Taken together, this means that we now have to enable the safe-guards of -Git v1.9.5 also in WSL: it is possible to access a `.git` directory -inside `/mnt/c/` via the 8.3 name `git~1` (unless short name generation -was disabled manually). Since regular Linux distributions run in WSL, -this means we have to enable `core.protectNTFS` at least on Linux, too. - -To enable Services for Macintosh in Windows NT to store so-called -resource forks, NTFS introduced "Alternate Data Streams". Essentially, -these constitute additional metadata that are connected to (and copied -with) their associated files, and they are accessed via pseudo file -names of the form `filename::`. - -In a recent patch, we extended `core.protectNTFS` to also protect -against accesses via NTFS Alternate Data Streams, e.g. to prevent -contents of the `.git/` directory to be "tracked" via yet another -alternative file name. - -While it is not possible (at least by default) to access files via NTFS -Alternate Data Streams from within WSL, the defaults on macOS when -mounting network shares via SMB _do_ allow accessing files and -directories in that way. Therefore, we need to enable `core.protectNTFS` -on macOS by default, too, and really, on any Operating System that can -mount network shares via SMB/CIFS. - -A couple of approaches were considered for fixing this: - -1. We could perform a dynamic NTFS check similar to the `core.symlinks` - check in `init`/`clone`: instead of trying to create a symbolic link - in the `.git/` directory, we could create a test file and try to - access `.git/config` via 8.3 name and/or Alternate Data Stream. - -2. We could simply "flip the switch" on `core.protectNTFS`, to make it - "on by default". - -The obvious downside of 1. is that it won't protect worktrees that were -clone with a vulnerable Git version already. We considered patching code -paths that check out files to check whether we're running on an NTFS -system dynamically and persist the result in the repository-local config -setting `core.protectNTFS`, but in the end decided that this solution -would be too fragile, and too involved. - -The obvious downside of 2. is that everybody will have to "suffer" the -performance penalty incurred from calling `is_ntfs_dotgit()` on every -path, even in setups where. - -After the recent work to accelerate `is_ntfs_dotgit()` in most cases, -it looks as if the time spent on validating ten million random -file names increases only negligibly (less than 20ms, well within the -standard deviation of ~50ms). Therefore the benefits outweigh the cost. - -Another downside of this is that paths that might have been acceptable -previously now will be forbidden. Realistically, though, this is an -improvement because public Git hosters already would reject any `git -push` that contains such file names. - -Note: There might be a similar problem mounting HFS+ on Linux. However, -this scenario has been considered unlikely and in light of the cost (in -the aforementioned benchmark, `core.protectHFS = true` increased the -time from ~440ms to ~610ms), it was decided _not_ to touch the default -of `core.protectHFS`. - -This change addresses CVE-2019-1353. - -Reported-by: Nicolas Joly -Helped-by: Garima Singh -Signed-off-by: Johannes Schindelin ---- - config.mak.uname | 3 +-- - environment.c | 2 +- - 2 files changed, 2 insertions(+), 3 deletions(-) - -diff --git a/config.mak.uname b/config.mak.uname -index db7f06b..3e46a8e 100644 ---- a/config.mak.uname -+++ b/config.mak.uname -@@ -454,7 +454,6 @@ ifneq ($(USE_MSVC_CRTDBG),) - # Optionally enable memory leak reporting. - BASIC_CFLAGS += -DUSE_MSVC_CRTDBG - endif -- BASIC_CFLAGS += -DPROTECT_NTFS_DEFAULT=1 - # Always give "-Zi" to the compiler and "-debug" to linker (even in - # release mode) to force a PDB to be generated (like RelWithDebInfo). - BASIC_CFLAGS += -Zi -@@ -616,7 +615,7 @@ ifneq (,$(findstring MINGW,$(uname_S))) - compat/win32/path-utils.o \ - compat/win32/pthread.o compat/win32/syslog.o \ - compat/win32/dirent.o -- BASIC_CFLAGS += -DWIN32 -DPROTECT_NTFS_DEFAULT=1 -+ BASIC_CFLAGS += -DWIN32 - EXTLIBS += -lws2_32 - GITLIBS += git.res - PTHREAD_LIBS = -diff --git a/environment.c b/environment.c -index 89af47c..9f5f381 100644 ---- a/environment.c -+++ b/environment.c -@@ -80,7 +80,7 @@ - int protect_hfs = PROTECT_HFS_DEFAULT; - - #ifndef PROTECT_NTFS_DEFAULT --#define PROTECT_NTFS_DEFAULT 0 -+#define PROTECT_NTFS_DEFAULT 1 - #endif - int protect_ntfs = PROTECT_NTFS_DEFAULT; - const char *core_fsmonitor; --- -1.8.3.1 - diff --git a/CVE-2019-1354.patch b/CVE-2019-1354.patch deleted file mode 100644 index e8c1efb..0000000 --- a/CVE-2019-1354.patch +++ /dev/null @@ -1,105 +0,0 @@ -From e1d911dd4c7b76a5a8cec0f5c8de15981e34da83 Mon Sep 17 00:00:00 2001 -From: Johannes Schindelin -Date: Thu, 12 Sep 2019 14:54:05 +0200 -Subject: [PATCH] mingw: disallow backslash characters in tree objects' file - names - -The backslash character is not a valid part of a file name on Windows. -Hence it is dangerous to allow writing files that were unpacked from -tree objects, when the stored file name contains a backslash character: -it will be misinterpreted as directory separator. - -This not only causes ambiguity when a tree contains a blob `a\b` and a -tree `a` that contains a blob `b`, but it also can be used as part of an -attack vector to side-step the careful protections against writing into -the `.git/` directory during a clone of a maliciously-crafted -repository. - -Let's prevent that, addressing CVE-2019-1354. - -Note: we guard against backslash characters in tree objects' file names -_only_ on Windows (because on other platforms, even on those where NTFS -volumes can be mounted, the backslash character is _not_ a directory -separator), and _only_ when `core.protectNTFS = true` (because users -might need to generate tree objects for other platforms, of course -without touching the worktree, e.g. using `git update-index ---cacheinfo`). - -Signed-off-by: Johannes Schindelin ---- - t/t1450-fsck.sh | 1 + - t/t7415-submodule-names.sh | 8 +++++--- - t/t9350-fast-export.sh | 1 + - tree-walk.c | 6 ++++++ - 4 files changed, 13 insertions(+), 3 deletions(-) - -diff --git a/t/t1450-fsck.sh b/t/t1450-fsck.sh -index cb4b66e..33c955f 100755 ---- a/t/t1450-fsck.sh -+++ b/t/t1450-fsck.sh -@@ -419,6 +419,7 @@ while read name path pretty; do - ( - git init $name-$type && - cd $name-$type && -+ git config core.protectNTFS false && - echo content >file && - git add file && - git commit -m base && -diff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh -index e1cd0a3..7c65e7a 100755 ---- a/t/t7415-submodule-names.sh -+++ b/t/t7415-submodule-names.sh -@@ -89,16 +89,18 @@ test_expect_success MINGW 'prevent git~1 squatting on Windows' ' - git hash-object -w --stdin)" && - rev="$(git rev-parse --verify HEAD)" && - hash="$(echo x | git hash-object -w --stdin)" && -- git update-index --add \ -+ git -c core.protectNTFS=false update-index --add \ - --cacheinfo 100644,$modules,.gitmodules \ - --cacheinfo 160000,$rev,c \ - --cacheinfo 160000,$rev,d\\a \ - --cacheinfo 100644,$hash,d./a/x \ - --cacheinfo 100644,$hash,d./a/..git && - test_tick && -- git commit -m "module" -+ git -c core.protectNTFS=false commit -m "module" && -+ test_must_fail git show HEAD: 2>err && -+ test_i18ngrep backslash err - ) && -- test_must_fail git \ -+ test_must_fail git -c core.protectNTFS=false \ - clone --recurse-submodules squatting squatting-clone 2>err && - test_i18ngrep "directory not empty" err && - ! grep gitdir squatting-clone/d/a/git~2 -diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh -index 866ddf6..e606207 100755 ---- a/t/t9350-fast-export.sh -+++ b/t/t9350-fast-export.sh -@@ -421,6 +421,7 @@ test_expect_success 'directory becomes symlink' ' - - test_expect_success 'fast-export quotes pathnames' ' - git init crazy-paths && -+ test_config -C crazy-paths core.protectNTFS false && - (cd crazy-paths && - blob=$(echo foo | git hash-object -w --stdin) && - git update-index --add \ -diff --git a/tree-walk.c b/tree-walk.c -index d459fed..54ff959 100644 ---- a/tree-walk.c -+++ b/tree-walk.c -@@ -41,6 +41,12 @@ static int decode_tree_entry(struct tree_desc *desc, const char *buf, unsigned l - strbuf_addstr(err, _("empty filename in tree entry")); - return -1; - } -+#ifdef GIT_WINDOWS_NATIVE -+ if (protect_ntfs && strchr(path, '\\')) { -+ strbuf_addf(err, _("filename in tree entry contains backslash: '%s'"), path); -+ return -1; -+ } -+#endif - len = strlen(path) + 1; - - /* Initialize the descriptor entry */ --- -1.8.3.1 - diff --git a/CVE-2019-1387.patch b/CVE-2019-1387.patch deleted file mode 100644 index 38c882a..0000000 --- a/CVE-2019-1387.patch +++ /dev/null @@ -1,181 +0,0 @@ -From a8dee3ca610f5a1d403634492136c887f83b59d2 Mon Sep 17 00:00:00 2001 -From: Johannes Schindelin -Date: Tue, 1 Oct 2019 23:27:18 +0200 -Subject: [PATCH] Disallow dubiously-nested submodule git directories - -Currently it is technically possible to let a submodule's git -directory point right into the git dir of a sibling submodule. - -Example: the git directories of two submodules with the names `hippo` -and `hippo/hooks` would be `.git/modules/hippo/` and -`.git/modules/hippo/hooks/`, respectively, but the latter is already -intended to house the former's hooks. - -In most cases, this is just confusing, but there is also a (quite -contrived) attack vector where Git can be fooled into mistaking remote -content for file contents it wrote itself during a recursive clone. - -Let's plug this bug. - -To do so, we introduce the new function `validate_submodule_git_dir()` -which simply verifies that no git dir exists for any leading directories -of the submodule name (if there are any). - -Note: this patch specifically continues to allow sibling modules names -of the form `core/lib`, `core/doc`, etc, as long as `core` is not a -submodule name. - -This fixes CVE-2019-1387. - -Reported-by: Nicolas Joly -Signed-off-by: Johannes Schindelin ---- - builtin/submodule--helper.c | 4 ++++ - submodule.c | 49 +++++++++++++++++++++++++++++++++++++++++++-- - submodule.h | 5 +++++ - t/t7415-submodule-names.sh | 23 +++++++++++++++++++++ - 4 files changed, 79 insertions(+), 2 deletions(-) - -diff --git a/builtin/submodule--helper.c b/builtin/submodule--helper.c -index f3ba6aa..a083b99 100644 ---- a/builtin/submodule--helper.c -+++ b/builtin/submodule--helper.c -@@ -1416,6 +1416,10 @@ static int module_clone(int argc, const char **argv, const char *prefix) - } else - path = xstrdup(path); - -+ if (validate_submodule_git_dir(sm_gitdir, name) < 0) -+ die(_("refusing to create/use '%s' in another submodule's " -+ "git dir"), sm_gitdir); -+ - if (!file_exists(sm_gitdir)) { - if (safe_create_leading_directories_const(sm_gitdir) < 0) - die(_("could not create directory '%s'"), sm_gitdir); -diff --git a/submodule.c b/submodule.c -index 0f199c5..9da7181 100644 ---- a/submodule.c -+++ b/submodule.c -@@ -1993,6 +1993,47 @@ int submodule_move_head(const char *path, - return ret; - } - -+int validate_submodule_git_dir(char *git_dir, const char *submodule_name) -+{ -+ size_t len = strlen(git_dir), suffix_len = strlen(submodule_name); -+ char *p; -+ int ret = 0; -+ -+ if (len <= suffix_len || (p = git_dir + len - suffix_len)[-1] != '/' || -+ strcmp(p, submodule_name)) -+ BUG("submodule name '%s' not a suffix of git dir '%s'", -+ submodule_name, git_dir); -+ -+ /* -+ * We prevent the contents of sibling submodules' git directories to -+ * clash. -+ * -+ * Example: having a submodule named `hippo` and another one named -+ * `hippo/hooks` would result in the git directories -+ * `.git/modules/hippo/` and `.git/modules/hippo/hooks/`, respectively, -+ * but the latter directory is already designated to contain the hooks -+ * of the former. -+ */ -+ for (; *p; p++) { -+ if (is_dir_sep(*p)) { -+ char c = *p; -+ -+ *p = '\0'; -+ if (is_git_directory(git_dir)) -+ ret = -1; -+ *p = c; -+ -+ if (ret < 0) -+ return error(_("submodule git dir '%s' is " -+ "inside git dir '%.*s'"), -+ git_dir, -+ (int)(p - git_dir), git_dir); -+ } -+ } -+ -+ return 0; -+} -+ - /* - * Embeds a single submodules git directory into the superprojects git dir, - * non recursively. -@@ -2000,7 +2041,7 @@ int submodule_move_head(const char *path, - static void relocate_single_git_dir_into_superproject(const char *path) - { - char *old_git_dir = NULL, *real_old_git_dir = NULL, *real_new_git_dir = NULL; -- const char *new_git_dir; -+ char *new_git_dir; - const struct submodule *sub; - - if (submodule_uses_worktrees(path)) -@@ -2018,10 +2059,14 @@ static void relocate_single_git_dir_into_superproject(const char *path) - if (!sub) - die(_("could not lookup name for submodule '%s'"), path); - -- new_git_dir = git_path("modules/%s", sub->name); -+ new_git_dir = git_pathdup("modules/%s", sub->name); -+ if (validate_submodule_git_dir(new_git_dir, sub->name) < 0) -+ die(_("refusing to move '%s' into an existing git dir"), -+ real_old_git_dir); - if (safe_create_leading_directories_const(new_git_dir) < 0) - die(_("could not create directory '%s'"), new_git_dir); - real_new_git_dir = real_pathdup(new_git_dir, 1); -+ free(new_git_dir); - - fprintf(stderr, _("Migrating git directory of '%s%s' from\n'%s' to\n'%s'\n"), - get_super_prefix_or_empty(), path, -diff --git a/submodule.h b/submodule.h -index 8072e6d..c81ec1a 100644 ---- a/submodule.h -+++ b/submodule.h -@@ -124,6 +124,11 @@ int push_unpushed_submodules(struct repository *r, - */ - int submodule_to_gitdir(struct strbuf *buf, const char *submodule); - -+/* -+ * Make sure that no submodule's git dir is nested in a sibling submodule's. -+ */ -+int validate_submodule_git_dir(char *git_dir, const char *submodule_name); -+ - #define SUBMODULE_MOVE_HEAD_DRY_RUN (1<<0) - #define SUBMODULE_MOVE_HEAD_FORCE (1<<1) - int submodule_move_head(const char *path, -diff --git a/t/t7415-submodule-names.sh b/t/t7415-submodule-names.sh -index 3008ba8..a44578f 100755 ---- a/t/t7415-submodule-names.sh -+++ b/t/t7415-submodule-names.sh -@@ -224,4 +224,27 @@ test_expect_success MINGW 'prevent git~1 squatting on Windows' ' - ! grep gitdir squatting-clone/d/a/git~2 - ' - -+test_expect_success 'git dirs of sibling submodules must not be nested' ' -+ git init nested && -+ test_commit -C nested nested && -+ ( -+ cd nested && -+ cat >.gitmodules <<-EOF && -+ [submodule "hippo"] -+ url = . -+ path = thing1 -+ [submodule "hippo/hooks"] -+ url = . -+ path = thing2 -+ EOF -+ git clone . thing1 && -+ git clone . thing2 && -+ git add .gitmodules thing1 thing2 && -+ test_tick && -+ git commit -m nested -+ ) && -+ test_must_fail git clone --recurse-submodules nested clone 2>err && -+ test_i18ngrep "is inside git dir" err -+' -+ - test_done --- -1.8.3.1 - diff --git a/CVE-2019-19604.patch b/CVE-2019-19604.patch deleted file mode 100644 index 1d0161f..0000000 --- a/CVE-2019-19604.patch +++ /dev/null @@ -1,148 +0,0 @@ -From e904deb89d9a9669a76a426182506a084d3f6308 Mon Sep 17 00:00:00 2001 -From: Jonathan Nieder -Date: Thu, 5 Dec 2019 01:28:28 -0800 -Subject: [PATCH] submodule: reject submodule.update = !command in .gitmodules - -Since ac1fbbda2013 (submodule: do not copy unknown update mode from -.gitmodules, 2013-12-02), Git has been careful to avoid copying - - [submodule "foo"] - update = !run an arbitrary scary command - -from .gitmodules to a repository's local config, copying in the -setting 'update = none' instead. The gitmodules(5) manpage documents -the intention: - - The !command form is intentionally ignored here for security - reasons - -Unfortunately, starting with v2.20.0-rc0 (which integrated ee69b2a9 -(submodule--helper: introduce new update-module-mode helper, -2018-08-13, first released in v2.20.0-rc0)), there are scenarios where -we *don't* ignore it: if the config store contains no -submodule.foo.update setting, the submodule-config API falls back to -reading .gitmodules and the repository-supplied !command gets run -after all. - -This was part of a general change over time in submodule support to -read more directly from .gitmodules, since unlike .git/config it -allows a project to change values between branches and over time -(while still allowing .git/config to override things). But it was -never intended to apply to this kind of dangerous configuration. - -The behavior change was not advertised in ee69b2a9's commit message -and was missed in review. - -Let's take the opportunity to make the protection more robust, even in -Git versions that are technically not affected: instead of quietly -converting 'update = !command' to 'update = none', noisily treat it as -an error. Allowing the setting but treating it as meaning something -else was just confusing; users are better served by seeing the error -sooner. Forbidding the construct makes the semantics simpler and -means we can check for it in fsck (in a separate patch). - -As a result, the submodule-config API cannot read this value from -.gitmodules under any circumstance, and we can declare with confidence - - For security reasons, the '!command' form is not accepted - here. - -Reported-by: Joern Schneeweisz -Signed-off-by: Jonathan Nieder -Signed-off-by: Johannes Schindelin ---- - Documentation/gitmodules.txt | 5 ++--- - submodule-config.c | 10 +++++++++- - t/t7406-submodule-update.sh | 14 ++++++++------ - 3 files changed, 19 insertions(+), 10 deletions(-) - -diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt -index a66e95b..f260b55 100644 ---- a/Documentation/gitmodules.txt -+++ b/Documentation/gitmodules.txt -@@ -44,9 +44,8 @@ submodule..update:: - submodule init` to initialize the configuration variable of - the same name. Allowed values here are 'checkout', 'rebase', - 'merge' or 'none'. See description of 'update' command in -- linkgit:git-submodule[1] for their meaning. Note that the -- '!command' form is intentionally ignored here for security -- reasons. -+ linkgit:git-submodule[1] for their meaning. For security -+ reasons, the '!command' form is not accepted here. - - submodule..branch:: - A remote branch name for tracking updates in the upstream submodule. -diff --git a/submodule-config.c b/submodule-config.c -index 4264ee2..3acc6ad 100644 ---- a/submodule-config.c -+++ b/submodule-config.c -@@ -405,6 +405,13 @@ struct parse_config_parameter { - int overwrite; - }; - -+/* -+ * Parse a config item from .gitmodules. -+ * -+ * This does not handle submodule-related configuration from the main -+ * config store (.git/config, etc). Callers are responsible for -+ * checking for overrides in the main config store when appropriate. -+ */ - static int parse_config(const char *var, const char *value, void *data) - { - struct parse_config_parameter *me = data; -@@ -482,7 +489,8 @@ static int parse_config(const char *var, const char *value, void *data) - warn_multiple_config(me->treeish_name, submodule->name, - "update"); - else if (parse_submodule_update_strategy(value, -- &submodule->update_strategy) < 0) -+ &submodule->update_strategy) < 0 || -+ submodule->update_strategy.type == SM_UPDATE_COMMAND) - die(_("invalid value for %s"), var); - } else if (!strcmp(item.buf, "shallow")) { - if (!me->overwrite && submodule->recommend_shallow != -1) -diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh -index c973278..031ae85 100755 ---- a/t/t7406-submodule-update.sh -+++ b/t/t7406-submodule-update.sh -@@ -407,12 +407,12 @@ test_expect_success 'submodule update - command in .git/config' ' - ) - ' - --test_expect_success 'submodule update - command in .gitmodules is ignored' ' -+test_expect_success 'submodule update - command in .gitmodules is rejected' ' - test_when_finished "git -C super reset --hard HEAD^" && - git -C super config -f .gitmodules submodule.submodule.update "!false" && - git -C super commit -a -m "add command to .gitmodules file" && - git -C super/submodule reset --hard $submodulesha1^ && -- git -C super submodule update submodule -+ test_must_fail git -C super submodule update submodule - ' - - cat << EOF >expect -@@ -481,6 +481,9 @@ test_expect_success 'recursive submodule update - command in .git/config catches - ' - - test_expect_success 'submodule init does not copy command into .git/config' ' -+ test_when_finished "git -C super update-index --force-remove submodule1" && -+ test_when_finished git config -f super/.gitmodules \ -+ --remove-section submodule.submodule1 && - (cd super && - git ls-files -s submodule >out && - H=$(cut -d" " -f2 out) && -@@ -489,10 +492,9 @@ test_expect_success 'submodule init does not copy command into .git/config' ' - git config -f .gitmodules submodule.submodule1.path submodule1 && - git config -f .gitmodules submodule.submodule1.url ../submodule && - git config -f .gitmodules submodule.submodule1.update !false && -- git submodule init submodule1 && -- echo "none" >expect && -- git config submodule.submodule1.update >actual && -- test_cmp expect actual -+ test_must_fail git submodule init submodule1 && -+ test_expect_code 1 git config submodule.submodule1.update >actual && -+ test_must_be_empty actual - ) - ' - --- -1.8.3.1 - diff --git a/CVE-2020-11008-1.patch b/CVE-2020-11008-1.patch deleted file mode 100644 index 7b4ca7c..0000000 --- a/CVE-2020-11008-1.patch +++ /dev/null @@ -1,63 +0,0 @@ -From a88dbd2f8c7fd8c1e2f63483da03bd6928e8791f Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Sun, 19 Apr 2020 01:36:02 -0400 -Subject: [PATCH] t0300: make "quit" helper more realistic - -We test a toy credential helper that writes "quit=1" and confirms that -we stop running other helpers. However, that helper is unrealistic in -that it does not bother to read its stdin at all. - -For now we don't send any input to it, because we feed git-credential a -blank credential. But that will change in the next patch, which will -cause this test to racily fail, as git-credential will get SIGPIPE -writing to the helper rather than exiting because it was asked to. - -Let's make this one-off helper more like our other sample helpers, and -have it source the "dump" script. That will read stdin, fixing the -SIGPIPE problem. But it will also write what it sees to stderr. We can -make the test more robust by checking that output, which confirms that -we do run the quit helper, don't run any other helpers, and exit for the -reason we expected. - -Signed-off-by: Jeff King -Signed-off-by: Jonathan Nieder ---- - t/t0300-credentials.sh | 16 +++++++++++++--- - 1 file changed, 13 insertions(+), 3 deletions(-) - ---- a/t/t0300-credentials.sh -+++ b/t/t0300-credentials.sh -@@ -22,6 +22,11 @@ test_expect_success 'setup helper script - exit 0 - EOF - -+ write_script git-credential-quit <<-\EOF && -+ . ./dump -+ echo quit=1 -+ EOF -+ - write_script git-credential-verbatim <<-\EOF && - user=$1; shift - pass=$1; shift -@@ -291,10 +296,15 @@ test_expect_success 'http paths can be p - - test_expect_success 'helpers can abort the process' ' - test_must_fail git \ -- -c credential.helper="!f() { echo quit=1; }; f" \ -+ -c credential.helper=quit \ - -c credential.helper="verbatim foo bar" \ -- credential fill >stdout && -- test_must_be_empty stdout -+ credential fill >stdout 2>stderr && -+ test_must_be_empty stdout && -+ cat >expect <<-\EOF && -+ quit: get -+ fatal: credential helper '\''quit'\'' told us to quit -+ EOF -+ test_i18ncmp expect stderr - ' - - test_expect_success 'empty helper spec resets helper list' ' --- -1.8.3.1 - diff --git a/CVE-2020-11008-2.patch b/CVE-2020-11008-2.patch deleted file mode 100644 index 1ef8fa2..0000000 --- a/CVE-2020-11008-2.patch +++ /dev/null @@ -1,285 +0,0 @@ -From 73aafe9bc27585554181c58871a25e6d0f58a3dc Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Sat, 18 Apr 2020 20:47:30 -0700 -Subject: [PATCH] t0300: use more realistic inputs - -Many of the tests in t0300 give partial inputs to git-credential, -omitting a protocol or hostname. We're checking only high-level things -like whether and how helpers are invoked at all, and we don't care about -specific hosts. However, in preparation for tightening up the rules -about when we're willing to run a helper, let's start using input that's -a bit more realistic: pretend as if http://example.com is being -examined. - -This shouldn't change the point of any of the tests, but do note we have -to adjust the expected output to accommodate this (filling a credential -will repeat back the protocol/host fields to stdout, and the helper -debug messages and askpass prompt will change on stderr). - -Signed-off-by: Jeff King -Reviewed-by: Taylor Blau -Signed-off-by: Jonathan Nieder ---- - t/t0300-credentials.sh | 89 ++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 85 insertions(+), 4 deletions(-) - ---- a/t/t0300-credentials.sh -+++ b/t/t0300-credentials.sh -@@ -40,43 +40,71 @@ test_expect_success 'setup helper script - - test_expect_success 'credential_fill invokes helper' ' - check fill "verbatim foo bar" <<-\EOF -+ protocol=http -+ host=example.com - -- -+ protocol=http -+ host=example.com - username=foo - password=bar - -- - verbatim: get -+ verbatim: protocol=http -+ verbatim: host=example.com - EOF - ' - - test_expect_success 'credential_fill invokes multiple helpers' ' - check fill useless "verbatim foo bar" <<-\EOF -+ protocol=http -+ host=example.com - -- -+ protocol=http -+ host=example.com - username=foo - password=bar - -- - useless: get -+ useless: protocol=http -+ useless: host=example.com - verbatim: get -+ verbatim: protocol=http -+ verbatim: host=example.com - EOF - ' - - test_expect_success 'credential_fill stops when we get a full response' ' - check fill "verbatim one two" "verbatim three four" <<-\EOF -+ protocol=http -+ host=example.com - -- -+ protocol=http -+ host=example.com - username=one - password=two - -- - verbatim: get -+ verbatim: protocol=http -+ verbatim: host=example.com - EOF - ' - - test_expect_success 'credential_fill continues through partial response' ' - check fill "verbatim one \"\"" "verbatim two three" <<-\EOF -+ protocol=http -+ host=example.com - -- -+ protocol=http -+ host=example.com - username=two - password=three - -- - verbatim: get -+ verbatim: protocol=http -+ verbatim: host=example.com - verbatim: get -+ verbatim: protocol=http -+ verbatim: host=example.com - verbatim: username=one - EOF - ' -@@ -102,14 +130,20 @@ test_expect_success 'credential_fill pas - - test_expect_success 'credential_approve calls all helpers' ' - check approve useless "verbatim one two" <<-\EOF -+ protocol=http -+ host=example.com - username=foo - password=bar - -- - -- - useless: store -+ useless: protocol=http -+ useless: host=example.com - useless: username=foo - useless: password=bar - verbatim: store -+ verbatim: protocol=http -+ verbatim: host=example.com - verbatim: username=foo - verbatim: password=bar - EOF -@@ -117,6 +151,8 @@ test_expect_success 'credential_approve - - test_expect_success 'do not bother storing password-less credential' ' - check approve useless <<-\EOF -+ protocol=http -+ host=example.com - username=foo - -- - -- -@@ -126,14 +162,20 @@ test_expect_success 'do not bother stori - - test_expect_success 'credential_reject calls all helpers' ' - check reject useless "verbatim one two" <<-\EOF -+ protocol=http -+ host=example.com - username=foo - password=bar - -- - -- - useless: erase -+ useless: protocol=http -+ useless: host=example.com - useless: username=foo - useless: password=bar - verbatim: erase -+ verbatim: protocol=http -+ verbatim: host=example.com - verbatim: username=foo - verbatim: password=bar - EOF -@@ -141,33 +183,49 @@ test_expect_success 'credential_reject c - - test_expect_success 'usernames can be preserved' ' - check fill "verbatim \"\" three" <<-\EOF -+ protocol=http -+ host=example.com - username=one - -- -+ protocol=http -+ host=example.com - username=one - password=three - -- - verbatim: get -+ verbatim: protocol=http -+ verbatim: host=example.com - verbatim: username=one - EOF - ' - - test_expect_success 'usernames can be overridden' ' - check fill "verbatim two three" <<-\EOF -+ protocol=http -+ host=example.com - username=one - -- -+ protocol=http -+ host=example.com - username=two - password=three - -- - verbatim: get -+ verbatim: protocol=http -+ verbatim: host=example.com - verbatim: username=one - EOF - ' - - test_expect_success 'do not bother completing already-full credential' ' - check fill "verbatim three four" <<-\EOF -+ protocol=http -+ host=example.com - username=one - password=two - -- -+ protocol=http -+ host=example.com - username=one - password=two - -- -@@ -179,23 +237,31 @@ test_expect_success 'do not bother compl - # askpass helper is run, we know the internal getpass is working. - test_expect_success 'empty helper list falls back to internal getpass' ' - check fill <<-\EOF -+ protocol=http -+ host=example.com - -- -+ protocol=http -+ host=example.com - username=askpass-username - password=askpass-password - -- -- askpass: Username: -- askpass: Password: -+ askpass: Username for '\''http://example.com'\'': -+ askpass: Password for '\''http://askpass-username@example.com'\'': - EOF - ' - - test_expect_success 'internal getpass does not ask for known username' ' - check fill <<-\EOF -+ protocol=http -+ host=example.com - username=foo - -- -+ protocol=http -+ host=example.com - username=foo - password=askpass-password - -- -- askpass: Password: -+ askpass: Password for '\''http://foo@example.com'\'': - EOF - ' - -@@ -207,7 +273,11 @@ HELPER="!f() { - test_expect_success 'respect configured credentials' ' - test_config credential.helper "$HELPER" && - check fill <<-\EOF -+ protocol=http -+ host=example.com - -- -+ protocol=http -+ host=example.com - username=foo - password=bar - -- -@@ -298,10 +368,15 @@ test_expect_success 'helpers can abort t - test_must_fail git \ - -c credential.helper=quit \ - -c credential.helper="verbatim foo bar" \ -- credential fill >stdout 2>stderr && -+ credential fill >stdout 2>stderr <<-\EOF && -+ protocol=http -+ host=example.com -+ EOF - test_must_be_empty stdout && - cat >expect <<-\EOF && - quit: get -+ quit: protocol=http -+ quit: host=example.com - fatal: credential helper '\''quit'\'' told us to quit - EOF - test_i18ncmp expect stderr -@@ -310,11 +385,17 @@ test_expect_success 'helpers can abort t - test_expect_success 'empty helper spec resets helper list' ' - test_config credential.helper "verbatim file file" && - check fill "" "verbatim cmdline cmdline" <<-\EOF -+ protocol=http -+ host=example.com - -- -+ protocol=http -+ host=example.com - username=cmdline - password=cmdline - -- - verbatim: get -+ verbatim: protocol=http -+ verbatim: host=example.com - EOF - ' - --- -1.8.3.1 - diff --git a/CVE-2020-11008-3.patch b/CVE-2020-11008-3.patch deleted file mode 100644 index ca65c3d..0000000 --- a/CVE-2020-11008-3.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 24036686c4af84c9e84e486ef3debab6e6d8e6b5 Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Sat, 18 Apr 2020 20:48:05 -0700 -Subject: [PATCH] credential: parse URL without host as empty host, not unset - -We may feed a URL like "cert:///path/to/cert.pem" into the credential -machinery to get the key for a client-side certificate. That -credential has no hostname field, which is about to be disallowed (to -avoid confusion with protocols where a helper _would_ expect a -hostname). - -This means as of the next patch, credential helpers won't work for -unlocking certs. Let's fix that by doing two things: - - - when we parse a url with an empty host, set the host field to the - empty string (asking only to match stored entries with an empty - host) rather than NULL (asking to match _any_ host). - - - when we build a cert:// credential by hand, similarly assign an - empty string - -It's the latter that is more likely to impact real users in practice, -since it's what's used for http connections. But we don't have good -infrastructure to test it. - -The url-parsing version will help anybody using git-credential in a -script, and is easy to test. - -Signed-off-by: Jeff King -Reviewed-by: Taylor Blau -Signed-off-by: Jonathan Nieder ---- - credential.c | 3 +-- - http.c | 1 + - t/t0300-credentials.sh | 17 +++++++++++++++++ - 3 files changed, 19 insertions(+), 2 deletions(-) - ---- a/credential.c -+++ b/credential.c -@@ -376,8 +376,7 @@ int credential_from_url_gently(struct cr - - if (proto_end - url > 0) - c->protocol = xmemdupz(url, proto_end - url); -- if (slash - host > 0) -- c->host = url_decode_mem(host, slash - host); -+ c->host = url_decode_mem(host, slash - host); - /* Trim leading and trailing slashes from path */ - while (*slash == '/') - slash++; ---- a/http.c -+++ b/http.c -@@ -554,6 +554,7 @@ static int has_cert_password(void) - return 0; - if (!cert_auth.password) { - cert_auth.protocol = xstrdup("cert"); -+ cert_auth.host = xstrdup(""); - cert_auth.username = xstrdup(""); - cert_auth.path = xstrdup(ssl_cert); - credential_fill(&cert_auth); ---- a/t/t0300-credentials.sh -+++ b/t/t0300-credentials.sh -@@ -413,4 +413,21 @@ test_expect_success 'url parser ignores - EOF - ' - -+test_expect_success 'host-less URLs are parsed as empty host' ' -+ check fill "verbatim foo bar" <<-\EOF -+ url=cert:///path/to/cert.pem -+ -- -+ protocol=cert -+ host= -+ path=path/to/cert.pem -+ username=foo -+ password=bar -+ -- -+ verbatim: get -+ verbatim: protocol=cert -+ verbatim: host= -+ verbatim: path=path/to/cert.pem -+ EOF -+' -+ - test_done --- -1.8.3.1 - diff --git a/CVE-2020-11008-4.patch b/CVE-2020-11008-4.patch deleted file mode 100644 index 93c70a0..0000000 --- a/CVE-2020-11008-4.patch +++ /dev/null @@ -1,164 +0,0 @@ -From 8ba8ed568e2a3b75ee84c49ddffb026fde1a0a91 Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Sat, 18 Apr 2020 20:50:48 -0700 -Subject: [PATCH] credential: refuse to operate when missing host or protocol - -The credential helper protocol was designed to be very flexible: the -fields it takes as input are treated as a pattern, and any missing -fields are taken as wildcards. This allows unusual things like: - - echo protocol=https | git credential reject - -to delete all stored https credentials (assuming the helpers themselves -treat the input that way). But when helpers are invoked automatically by -Git, this flexibility works against us. If for whatever reason we don't -have a "host" field, then we'd match _any_ host. When you're filling a -credential to send to a remote server, this is almost certainly not what -you want. - -Prevent this at the layer that writes to the credential helper. Add a -check to the credential API that the host and protocol are always passed -in, and add an assertion to the credential_write function that speaks -credential helper protocol to be doubly sure. - -There are a few ways this can be triggered in practice: - - - the "git credential" command passes along arbitrary credential - parameters it reads from stdin. - - - until the previous patch, when the host field of a URL is empty, we - would leave it unset (rather than setting it to the empty string) - - - a URL like "example.com/foo.git" is treated by curl as if "http://" - was present, but our parser sees it as a non-URL and leaves all - fields unset - - - the recent fix for URLs with embedded newlines blanks the URL but - otherwise continues. Rather than having the desired effect of - looking up no credential at all, many helpers will return _any_ - credential - -Our earlier test for an embedded newline didn't catch this because it -only checked that the credential was cleared, but didn't configure an -actual helper. Configuring the "verbatim" helper in the test would show -that it is invoked (it's obviously a silly helper which doesn't look at -its input, but the point is that it shouldn't be run at all). Since -we're switching this case to die(), we don't need to bother with a -helper. We can see the new behavior just by checking that the operation -fails. - -We'll add new tests covering partial input as well (these can be -triggered through various means with url-parsing, but it's simpler to -just check them directly, as we know we are covered even if the url -parser changes behavior in the future). - -[jn: changed to die() instead of logging and showing a manual - username/password prompt] - -Reported-by: Carlo Arenas -Signed-off-by: Jeff King -Signed-off-by: Jonathan Nieder ---- - credential.c | 20 ++++++++++++++------ - t/t0300-credentials.sh | 34 ++++++++++++++++++++++++++-------- - 2 files changed, 40 insertions(+), 14 deletions(-) - ---- a/credential.c -+++ b/credential.c -@@ -89,6 +89,11 @@ static int proto_is_http(const char *s) - - static void credential_apply_config(struct credential *c) - { -+ if (!c->host) -+ die(_("refusing to work with credential missing host field")); -+ if (!c->protocol) -+ die(_("refusing to work with credential missing protocol field")); -+ - if (c->configured) - return; - git_config(credential_config_callback, c); -@@ -191,8 +196,11 @@ int credential_read(struct credential *c - return 0; - } - --static void credential_write_item(FILE *fp, const char *key, const char *value) -+static void credential_write_item(FILE *fp, const char *key, const char *value, -+ int required) - { -+ if (!value && required) -+ BUG("credential value for %s is missing", key); - if (!value) - return; - if (strchr(value, '\n')) -@@ -202,11 +210,11 @@ static void credential_write_item(FILE * - - void credential_write(const struct credential *c, FILE *fp) - { -- credential_write_item(fp, "protocol", c->protocol); -- credential_write_item(fp, "host", c->host); -- credential_write_item(fp, "path", c->path); -- credential_write_item(fp, "username", c->username); -- credential_write_item(fp, "password", c->password); -+ credential_write_item(fp, "protocol", c->protocol, 1); -+ credential_write_item(fp, "host", c->host, 1); -+ credential_write_item(fp, "path", c->path, 0); -+ credential_write_item(fp, "username", c->username, 0); -+ credential_write_item(fp, "password", c->password, 0); - } - - static int run_credential_helper(struct credential *c, ---- a/t/t0300-credentials.sh -+++ b/t/t0300-credentials.sh -@@ -399,18 +399,16 @@ test_expect_success 'empty helper spec r - EOF - ' - --test_expect_success 'url parser ignores embedded newlines' ' -- check fill <<-EOF -+test_expect_success 'url parser rejects embedded newlines' ' -+ test_must_fail git credential fill 2>stderr <<-\EOF && - url=https://one.example.com?%0ahost=two.example.com/ -- -- -- username=askpass-username -- password=askpass-password -- -- -+ EOF -+ cat >expect <<-\EOF && - warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/ - warning: skipping credential lookup for url: https://one.example.com?%0ahost=two.example.com/ -- askpass: Username: -- askpass: Password: -+ fatal: refusing to work with credential missing host field - EOF -+ test_i18ncmp expect stderr - ' - - test_expect_success 'host-less URLs are parsed as empty host' ' -@@ -430,4 +428,24 @@ test_expect_success 'host-less URLs are - EOF - ' - -+test_expect_success 'credential system refuses to work with missing host' ' -+ test_must_fail git credential fill 2>stderr <<-\EOF && -+ protocol=http -+ EOF -+ cat >expect <<-\EOF && -+ fatal: refusing to work with credential missing host field -+ EOF -+ test_i18ncmp expect stderr -+' -+ -+test_expect_success 'credential system refuses to work with missing protocol' ' -+ test_must_fail git credential fill 2>stderr <<-\EOF && -+ host=example.com -+ EOF -+ cat >expect <<-\EOF && -+ fatal: refusing to work with credential missing protocol field -+ EOF -+ test_i18ncmp expect stderr -+' -+ - test_done --- -1.8.3.1 - diff --git a/CVE-2020-11008-5.patch b/CVE-2020-11008-5.patch deleted file mode 100644 index a35b698..0000000 --- a/CVE-2020-11008-5.patch +++ /dev/null @@ -1,205 +0,0 @@ -From a2b26ffb1a81aa23dd14453f4db05d8fe24ee7cc Mon Sep 17 00:00:00 2001 -From: Jonathan Nieder -Date: Sat, 18 Apr 2020 20:52:34 -0700 -Subject: [PATCH] fsck: convert gitmodules url to URL passed to curl - -In 07259e74ec1 (fsck: detect gitmodules URLs with embedded newlines, -2020-03-11), git fsck learned to check whether URLs in .gitmodules could -be understood by the credential machinery when they are handled by -git-remote-curl. - -However, the check is overbroad: it checks all URLs instead of only -URLs that would be passed to git-remote-curl. In principle a git:// or -file:/// URL does not need to follow the same conventions as an http:// -URL; in particular, git:// and file:// protocols are not succeptible to -issues in the credential API because they do not support attaching -credentials. - -In the HTTP case, the URL in .gitmodules does not always match the URL -that would be passed to git-remote-curl and the credential machinery: -Git's URL syntax allows specifying a remote helper followed by a "::" -delimiter and a URL to be passed to it, so that - - git ls-remote http::https://example.com/repo.git - -invokes git-remote-http with https://example.com/repo.git as its URL -argument. With today's checks, that distinction does not make a -difference, but for a check we are about to introduce (for empty URL -schemes) it will matter. - -.gitmodules files also support relative URLs. To ensure coverage for the -https based embedded-newline attack, urldecode and check them directly -for embedded newlines. - -Helped-by: Jeff King -Signed-off-by: Jonathan Nieder -Reviewed-by: Jeff King ---- - fsck.c | 94 +++++++++++++++++++++++++++++++++-- - t/t7416-submodule-dash-url.sh | 29 +++++++++++ - 2 files changed, 118 insertions(+), 5 deletions(-) - ---- a/fsck.c -+++ b/fsck.c -@@ -9,6 +9,7 @@ - #include "tag.h" - #include "fsck.h" - #include "refs.h" -+#include "url.h" - #include "utf8.h" - #include "decorate.h" - #include "oidset.h" -@@ -983,17 +984,100 @@ static int fsck_tag(struct tag *tag, con - return fsck_tag_buffer(tag, data, size, options); - } - -+/* -+ * Like builtin/submodule--helper.c's starts_with_dot_slash, but without -+ * relying on the platform-dependent is_dir_sep helper. -+ * -+ * This is for use in checking whether a submodule URL is interpreted as -+ * relative to the current directory on any platform, since \ is a -+ * directory separator on Windows but not on other platforms. -+ */ -+static int starts_with_dot_slash(const char *str) -+{ -+ return str[0] == '.' && (str[1] == '/' || str[1] == '\\'); -+} -+ -+/* -+ * Like starts_with_dot_slash, this is a variant of submodule--helper's -+ * helper of the same name with the twist that it accepts backslash as a -+ * directory separator even on non-Windows platforms. -+ */ -+static int starts_with_dot_dot_slash(const char *str) -+{ -+ return str[0] == '.' && starts_with_dot_slash(str + 1); -+} -+ -+static int submodule_url_is_relative(const char *url) -+{ -+ return starts_with_dot_slash(url) || starts_with_dot_dot_slash(url); -+} -+ -+/* -+ * Check whether a transport is implemented by git-remote-curl. -+ * -+ * If it is, returns 1 and writes the URL that would be passed to -+ * git-remote-curl to the "out" parameter. -+ * -+ * Otherwise, returns 0 and leaves "out" untouched. -+ * -+ * Examples: -+ * http::https://example.com/repo.git -> 1, https://example.com/repo.git -+ * https://example.com/repo.git -> 1, https://example.com/repo.git -+ * git://example.com/repo.git -> 0 -+ * -+ * This is for use in checking for previously exploitable bugs that -+ * required a submodule URL to be passed to git-remote-curl. -+ */ -+static int url_to_curl_url(const char *url, const char **out) -+{ -+ /* -+ * We don't need to check for case-aliases, "http.exe", and so -+ * on because in the default configuration, is_transport_allowed -+ * prevents URLs with those schemes from being cloned -+ * automatically. -+ */ -+ if (skip_prefix(url, "http::", out) || -+ skip_prefix(url, "https::", out) || -+ skip_prefix(url, "ftp::", out) || -+ skip_prefix(url, "ftps::", out)) -+ return 1; -+ if (starts_with(url, "http://") || -+ starts_with(url, "https://") || -+ starts_with(url, "ftp://") || -+ starts_with(url, "ftps://")) { -+ *out = url; -+ return 1; -+ } -+ return 0; -+} -+ - static int check_submodule_url(const char *url) - { -- struct credential c = CREDENTIAL_INIT; -- int ret; -+ const char *curl_url; - - if (looks_like_command_line_option(url)) - return -1; - -- ret = credential_from_url_gently(&c, url, 1); -- credential_clear(&c); -- return ret; -+ if (submodule_url_is_relative(url)) { -+ /* -+ * This could be appended to an http URL and url-decoded; -+ * check for malicious characters. -+ */ -+ char *decoded = url_decode(url); -+ int has_nl = !!strchr(decoded, '\n'); -+ free(decoded); -+ if (has_nl) -+ return -1; -+ } -+ -+ else if (url_to_curl_url(url, &curl_url)) { -+ struct credential c = CREDENTIAL_INIT; -+ int ret = credential_from_url_gently(&c, curl_url, 1); -+ credential_clear(&c); -+ return ret; -+ } -+ -+ return 0; - } - - struct fsck_gitmodules_data { ---- a/t/t7416-submodule-dash-url.sh -+++ b/t/t7416-submodule-dash-url.sh -@@ -60,6 +60,20 @@ test_expect_success 'trailing backslash - test_i18ngrep ! "unknown option" err - ' - -+test_expect_success 'fsck permits embedded newline with unrecognized scheme' ' -+ git checkout --orphan newscheme && -+ cat >.gitmodules <<-\EOF && -+ [submodule "foo"] -+ url = "data://acjbkd%0akajfdickajkd" -+ EOF -+ git add .gitmodules && -+ git commit -m "gitmodules with unrecognized scheme" && -+ test_when_finished "rm -rf dst" && -+ git init --bare dst && -+ git -C dst config transfer.fsckObjects true && -+ git push dst HEAD -+' -+ - test_expect_success 'fsck rejects embedded newline in url' ' - # create an orphan branch to avoid existing .gitmodules objects - git checkout --orphan newline && -@@ -72,6 +86,21 @@ test_expect_success 'fsck rejects embedd - test_when_finished "rm -rf dst" && - git init --bare dst && - git -C dst config transfer.fsckObjects true && -+ test_must_fail git push dst HEAD 2>err && -+ grep gitmodulesUrl err -+' -+ -+test_expect_success 'fsck rejects embedded newline in relative url' ' -+ git checkout --orphan relative-newline && -+ cat >.gitmodules <<-\EOF && -+ [submodule "foo"] -+ url = "./%0ahost=two.example.com/foo.git" -+ EOF -+ git add .gitmodules && -+ git commit -m "relative url with newline" && -+ test_when_finished "rm -rf dst" && -+ git init --bare dst && -+ git -C dst config transfer.fsckObjects true && - test_must_fail git push dst HEAD 2>err && - grep gitmodulesUrl err - ' --- -1.8.3.1 - diff --git a/CVE-2020-11008-6.patch b/CVE-2020-11008-6.patch deleted file mode 100644 index b58fc67..0000000 --- a/CVE-2020-11008-6.patch +++ /dev/null @@ -1,75 +0,0 @@ -From fe29a9b7b0236d3d45c254965580d6aff7fa8504 Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Sat, 18 Apr 2020 20:53:09 -0700 -Subject: [PATCH] credential: die() when parsing invalid urls - -When we try to initialize credential loading by URL and find that the -URL is invalid, we set all fields to NULL in order to avoid acting on -malicious input. Later when we request credentials, we diagonse the -erroneous input: - - fatal: refusing to work with credential missing host field - -This is problematic in two ways: - -- The message doesn't tell the user *why* we are missing the host - field, so they can't tell from this message alone how to recover. - There can be intervening messages after the original warning of - bad input, so the user may not have the context to put two and two - together. - -- The error only occurs when we actually need to get a credential. If - the URL permits anonymous access, the only encouragement the user gets - to correct their bogus URL is a quiet warning. - - This is inconsistent with the check we perform in fsck, where any use - of such a URL as a submodule is an error. - -When we see such a bogus URL, let's not try to be nice and continue -without helpers. Instead, die() immediately. This is simpler and -obviously safe. And there's very little chance of disrupting a normal -workflow. - -It's _possible_ that somebody has a legitimate URL with a raw newline in -it. It already wouldn't work with credential helpers, so this patch -steps that up from an inconvenience to "we will refuse to work with it -at all". If such a case does exist, we should figure out a way to work -with it (especially if the newline is only in the path component, which -we normally don't even pass to helpers). But until we see a real report, -we're better off being defensive. - -Reported-by: Carlo Arenas -Signed-off-by: Jeff King -Signed-off-by: Jonathan Nieder ---- - credential.c | 6 ++---- - t/t0300-credentials.sh | 3 +-- - 2 files changed, 3 insertions(+), 6 deletions(-) - ---- a/credential.c -+++ b/credential.c -@@ -408,8 +408,6 @@ int credential_from_url_gently(struct cr - - void credential_from_url(struct credential *c, const char *url) - { -- if (credential_from_url_gently(c, url, 0) < 0) { -- warning(_("skipping credential lookup for url: %s"), url); -- credential_clear(c); -- } -+ if (credential_from_url_gently(c, url, 0) < 0) -+ die(_("credential url cannot be parsed: %s"), url); - } ---- a/t/t0300-credentials.sh -+++ b/t/t0300-credentials.sh -@@ -405,8 +405,7 @@ test_expect_success 'url parser rejects - EOF - cat >expect <<-\EOF && - warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/ -- warning: skipping credential lookup for url: https://one.example.com?%0ahost=two.example.com/ -- fatal: refusing to work with credential missing host field -+ fatal: credential url cannot be parsed: https://one.example.com?%0ahost=two.example.com/ - EOF - test_i18ncmp expect stderr - ' --- -1.8.3.1 diff --git a/CVE-2020-11008-7.patch b/CVE-2020-11008-7.patch deleted file mode 100644 index 5fa360d..0000000 --- a/CVE-2020-11008-7.patch +++ /dev/null @@ -1,194 +0,0 @@ -From c44088ecc4b0722636e0a305f9608d3047197282 Mon Sep 17 00:00:00 2001 -From: Jonathan Nieder -Date: Sat, 18 Apr 2020 20:54:13 -0700 -Subject: [PATCH] credential: treat URL without scheme as invalid - -libcurl permits making requests without a URL scheme specified. In -this case, it guesses the URL from the hostname, so I can run - - git ls-remote http::ftp.example.com/path/to/repo - -and it would make an FTP request. - -Any user intentionally using such a URL is likely to have made a typo. -Unfortunately, credential_from_url is not able to determine the host and -protocol in order to determine appropriate credentials to send, and -until "credential: refuse to operate when missing host or protocol", -this resulted in another host's credentials being leaked to the named -host. - -Teach credential_from_url_gently to consider such a URL to be invalid -so that fsck can detect and block gitmodules files with such URLs, -allowing server operators to avoid serving them to downstream users -running older versions of Git. - -This also means that when such URLs are passed on the command line, Git -will print a clearer error so affected users can switch to the simpler -URL that explicitly specifies the host and protocol they intend. - -One subtlety: .gitmodules files can contain relative URLs, representing -a URL relative to the URL they were cloned from. The relative URL -resolver used for .gitmodules can follow ".." components out of the path -part and past the host part of a URL, meaning that such a relative URL -can be used to traverse from a https://foo.example.com/innocent -superproject to a https::attacker.example.com/exploit submodule. -Fortunately a leading ':' in the first path component after a series of -leading './' and '../' components is unlikely to show up in other -contexts, so we can catch this by detecting that pattern. - -Reported-by: Jeff King -Signed-off-by: Jonathan Nieder -Reviewed-by: Jeff King ---- - credential.c | 7 ++++-- - fsck.c | 47 +++++++++++++++++++++++++++++++++-- - t/t5550-http-fetch-dumb.sh | 7 ++---- - t/t7416-submodule-dash-url.sh | 32 ++++++++++++++++++++++++ - 4 files changed, 84 insertions(+), 9 deletions(-) - ---- a/credential.c -+++ b/credential.c -@@ -360,8 +360,11 @@ int credential_from_url_gently(struct cr - * (3) proto://:@/... - */ - proto_end = strstr(url, "://"); -- if (!proto_end) -- return 0; -+ if (!proto_end) { -+ if (!quiet) -+ warning(_("url has no scheme: %s"), url); -+ return -1; -+ } - cp = proto_end + 3; - at = strchr(cp, '@'); - colon = strchr(cp, ':'); ---- a/fsck.c -+++ b/fsck.c -@@ -1013,6 +1013,34 @@ static int submodule_url_is_relative(con - } - - /* -+ * Count directory components that a relative submodule URL should chop -+ * from the remote_url it is to be resolved against. -+ * -+ * In other words, this counts "../" components at the start of a -+ * submodule URL. -+ * -+ * Returns the number of directory components to chop and writes a -+ * pointer to the next character of url after all leading "./" and -+ * "../" components to out. -+ */ -+static int count_leading_dotdots(const char *url, const char **out) -+{ -+ int result = 0; -+ while (1) { -+ if (starts_with_dot_dot_slash(url)) { -+ result++; -+ url += strlen("../"); -+ continue; -+ } -+ if (starts_with_dot_slash(url)) { -+ url += strlen("./"); -+ continue; -+ } -+ *out = url; -+ return result; -+ } -+} -+/* - * Check whether a transport is implemented by git-remote-curl. - * - * If it is, returns 1 and writes the URL that would be passed to -@@ -1059,15 +1087,30 @@ static int check_submodule_url(const cha - return -1; - - if (submodule_url_is_relative(url)) { -+ char *decoded; -+ const char *next; -+ int has_nl; -+ - /* - * This could be appended to an http URL and url-decoded; - * check for malicious characters. - */ -- char *decoded = url_decode(url); -- int has_nl = !!strchr(decoded, '\n'); -+ decoded = url_decode(url); -+ has_nl = !!strchr(decoded, '\n'); -+ - free(decoded); - if (has_nl) - return -1; -+ -+ /* -+ * URLs which escape their root via "../" can overwrite -+ * the host field and previous components, resolving to -+ * URLs like https::example.com/submodule.git that were -+ * susceptible to CVE-2020-11008. -+ */ -+ if (count_leading_dotdots(url, &next) > 0 && -+ *next == ':') -+ return -1; - } - - else if (url_to_curl_url(url, &curl_url)) { ---- a/t/t5550-http-fetch-dumb.sh -+++ b/t/t5550-http-fetch-dumb.sh -@@ -321,11 +321,8 @@ test_expect_success 'git client does not - ' - - test_expect_success 'remote-http complains cleanly about malformed urls' ' -- # do not actually issue "list" or other commands, as we do not -- # want to rely on what curl would actually do with such a broken -- # URL. This is just about making sure we do not segfault during -- # initialization. -- test_must_fail git remote-http http::/example.com/repo.git -+ test_must_fail git remote-http http::/example.com/repo.git 2>stderr && -+ test_i18ngrep "url has no scheme" stderr - ' - - test_expect_success 'redirects can be forbidden/allowed' ' ---- a/t/t7416-submodule-dash-url.sh -+++ b/t/t7416-submodule-dash-url.sh -@@ -60,6 +60,38 @@ test_expect_success 'trailing backslash - test_i18ngrep ! "unknown option" err - ' - -+test_expect_success 'fsck rejects missing URL scheme' ' -+ git checkout --orphan missing-scheme && -+ cat >.gitmodules <<-\EOF && -+ [submodule "foo"] -+ url = http::one.example.com/foo.git -+ EOF -+ git add .gitmodules && -+ test_tick && -+ git commit -m "gitmodules with missing URL scheme" && -+ test_when_finished "rm -rf dst" && -+ git init --bare dst && -+ git -C dst config transfer.fsckObjects true && -+ test_must_fail git push dst HEAD 2>err && -+ grep gitmodulesUrl err -+' -+ -+test_expect_success 'fsck rejects relative URL resolving to missing scheme' ' -+ git checkout --orphan relative-missing-scheme && -+ cat >.gitmodules <<-\EOF && -+ [submodule "foo"] -+ url = "..\\../.\\../:one.example.com/foo.git" -+ EOF -+ git add .gitmodules && -+ test_tick && -+ git commit -m "gitmodules with relative URL that strips off scheme" && -+ test_when_finished "rm -rf dst" && -+ git init --bare dst && -+ git -C dst config transfer.fsckObjects true && -+ test_must_fail git push dst HEAD 2>err && -+ grep gitmodulesUrl err -+' -+ - test_expect_success 'fsck permits embedded newline with unrecognized scheme' ' - git checkout --orphan newscheme && - cat >.gitmodules <<-\EOF && --- -1.8.3.1 - diff --git a/CVE-2020-11008-8.patch b/CVE-2020-11008-8.patch deleted file mode 100644 index 5d0b05e..0000000 --- a/CVE-2020-11008-8.patch +++ /dev/null @@ -1,104 +0,0 @@ -From e7fab62b736cca3416660636e46f0be8386a5030 Mon Sep 17 00:00:00 2001 -From: Jonathan Nieder -Date: Sat, 18 Apr 2020 20:54:57 -0700 -Subject: [PATCH] credential: treat URL with empty scheme as invalid - -Until "credential: refuse to operate when missing host or protocol", -Git's credential handling code interpreted URLs with empty scheme to -mean "give me credentials matching this host for any protocol". - -Luckily libcurl does not recognize such URLs (it tries to look for a -protocol named "" and fails). Just in case that changes, let's reject -them within Git as well. This way, credential_from_url is guaranteed to -always produce a "struct credential" with protocol and host set. - -Signed-off-by: Jonathan Nieder ---- - credential.c | 5 ++--- - t/t5550-http-fetch-dumb.sh | 9 +++++++++ - t/t7416-submodule-dash-url.sh | 32 ++++++++++++++++++++++++++++++++ - 3 files changed, 43 insertions(+), 3 deletions(-) - ---- a/credential.c -+++ b/credential.c -@@ -360,7 +360,7 @@ int credential_from_url_gently(struct cr - * (3) proto://:@/... - */ - proto_end = strstr(url, "://"); -- if (!proto_end) { -+ if (!proto_end || proto_end == url) { - if (!quiet) - warning(_("url has no scheme: %s"), url); - return -1; -@@ -385,8 +385,7 @@ int credential_from_url_gently(struct cr - host = at + 1; - } - -- if (proto_end - url > 0) -- c->protocol = xmemdupz(url, proto_end - url); -+ c->protocol = xmemdupz(url, proto_end - url); - c->host = url_decode_mem(host, slash - host); - /* Trim leading and trailing slashes from path */ - while (*slash == '/') ---- a/t/t5550-http-fetch-dumb.sh -+++ b/t/t5550-http-fetch-dumb.sh -@@ -325,6 +325,15 @@ test_expect_success 'remote-http complai - test_i18ngrep "url has no scheme" stderr - ' - -+# NEEDSWORK: Writing commands to git-remote-curl can race against the latter -+# erroring out, producing SIGPIPE. Remove "ok=sigpipe" once transport-helper has -+# learned to handle early remote helper failures more cleanly. -+test_expect_success 'remote-http complains cleanly about empty scheme' ' -+ test_must_fail ok=sigpipe git ls-remote \ -+ http::${HTTPD_URL#http}/dumb/repo.git 2>stderr && -+ test_i18ngrep "url has no scheme" stderr -+' -+ - test_expect_success 'redirects can be forbidden/allowed' ' - test_must_fail git -c http.followRedirects=false \ - clone $HTTPD_URL/dumb-redir/repo.git dumb-redir && ---- a/t/t7416-submodule-dash-url.sh -+++ b/t/t7416-submodule-dash-url.sh -@@ -92,6 +92,38 @@ test_expect_success 'fsck rejects relati - grep gitmodulesUrl err - ' - -+test_expect_success 'fsck rejects empty URL scheme' ' -+ git checkout --orphan empty-scheme && -+ cat >.gitmodules <<-\EOF && -+ [submodule "foo"] -+ url = http::://one.example.com/foo.git -+ EOF -+ git add .gitmodules && -+ test_tick && -+ git commit -m "gitmodules with empty URL scheme" && -+ test_when_finished "rm -rf dst" && -+ git init --bare dst && -+ git -C dst config transfer.fsckObjects true && -+ test_must_fail git push dst HEAD 2>err && -+ grep gitmodulesUrl err -+' -+ -+test_expect_success 'fsck rejects relative URL resolving to empty scheme' ' -+ git checkout --orphan relative-empty-scheme && -+ cat >.gitmodules <<-\EOF && -+ [submodule "foo"] -+ url = ../../../:://one.example.com/foo.git -+ EOF -+ git add .gitmodules && -+ test_tick && -+ git commit -m "relative gitmodules URL resolving to empty scheme" && -+ test_when_finished "rm -rf dst" && -+ git init --bare dst && -+ git -C dst config transfer.fsckObjects true && -+ test_must_fail git push dst HEAD 2>err && -+ grep gitmodulesUrl err -+' -+ - test_expect_success 'fsck permits embedded newline with unrecognized scheme' ' - git checkout --orphan newscheme && - cat >.gitmodules <<-\EOF && --- -1.8.3.1 - diff --git a/CVE-2020-11008-9.patch b/CVE-2020-11008-9.patch deleted file mode 100644 index 05d3a2c..0000000 --- a/CVE-2020-11008-9.patch +++ /dev/null @@ -1,106 +0,0 @@ -From 1a3609e402a062ef7b11f197fe96c28cabca132c Mon Sep 17 00:00:00 2001 -From: Jonathan Nieder -Date: Sat, 18 Apr 2020 20:57:22 -0700 -Subject: [PATCH] fsck: reject URL with empty host in .gitmodules - -Git's URL parser interprets - - https:///example.com/repo.git - -to have no host and a path of "example.com/repo.git". Curl, on the -other hand, internally redirects it to https://example.com/repo.git. As -a result, until "credential: parse URL without host as empty host, not -unset", tricking a user into fetching from such a URL would cause Git to -send credentials for another host to example.com. - -Teach fsck to block and detect .gitmodules files using such a URL to -prevent sharing them with Git versions that are not yet protected. - -A relative URL in a .gitmodules file could also be used to trigger this. -The relative URL resolver used for .gitmodules does not normalize -sequences of slashes and can follow ".." components out of the path part -and to the host part of a URL, meaning that such a relative URL can be -used to traverse from a https://foo.example.com/innocent superproject to -a https:///attacker.example.com/exploit submodule. Fortunately, -redundant extra slashes in .gitmodules are rare, so we can catch this by -detecting one after a leading sequence of "./" and "../" components. - -Helped-by: Jeff King -Signed-off-by: Jonathan Nieder -Reviewed-by: Jeff King ---- - fsck.c | 10 +++++++--- - t/t7416-submodule-dash-url.sh | 32 ++++++++++++++++++++++++++++++++ - 2 files changed, 39 insertions(+), 3 deletions(-) - ---- a/fsck.c -+++ b/fsck.c -@@ -1105,17 +1105,21 @@ static int check_submodule_url(const cha - /* - * URLs which escape their root via "../" can overwrite - * the host field and previous components, resolving to -- * URLs like https::example.com/submodule.git that were -+ * URLs like https::example.com/submodule.git and -+ * https:///example.com/submodule.git that were - * susceptible to CVE-2020-11008. - */ - if (count_leading_dotdots(url, &next) > 0 && -- *next == ':') -+ (*next == ':' || *next == '/')) - return -1; - } - - else if (url_to_curl_url(url, &curl_url)) { - struct credential c = CREDENTIAL_INIT; -- int ret = credential_from_url_gently(&c, curl_url, 1); -+ int ret = 0; -+ if (credential_from_url_gently(&c, curl_url, 1) || -+ !*c.host) -+ ret = -1; - credential_clear(&c); - return ret; - } ---- a/t/t7416-submodule-dash-url.sh -+++ b/t/t7416-submodule-dash-url.sh -@@ -124,6 +124,38 @@ test_expect_success 'fsck rejects relati - grep gitmodulesUrl err - ' - -+test_expect_success 'fsck rejects empty hostname' ' -+ git checkout --orphan empty-host && -+ cat >.gitmodules <<-\EOF && -+ [submodule "foo"] -+ url = http:///one.example.com/foo.git -+ EOF -+ git add .gitmodules && -+ test_tick && -+ git commit -m "gitmodules with extra slashes" && -+ test_when_finished "rm -rf dst" && -+ git init --bare dst && -+ git -C dst config transfer.fsckObjects true && -+ test_must_fail git push dst HEAD 2>err && -+ grep gitmodulesUrl err -+' -+ -+test_expect_success 'fsck rejects relative url that produced empty hostname' ' -+ git checkout --orphan messy-relative && -+ cat >.gitmodules <<-\EOF && -+ [submodule "foo"] -+ url = ../../..//one.example.com/foo.git -+ EOF -+ git add .gitmodules && -+ test_tick && -+ git commit -m "gitmodules abusing relative_path" && -+ test_when_finished "rm -rf dst" && -+ git init --bare dst && -+ git -C dst config transfer.fsckObjects true && -+ test_must_fail git push dst HEAD 2>err && -+ grep gitmodulesUrl err -+' -+ - test_expect_success 'fsck permits embedded newline with unrecognized scheme' ' - git checkout --orphan newscheme && - cat >.gitmodules <<-\EOF && --- -1.8.3.1 - diff --git a/CVE-2020-5260.patch b/CVE-2020-5260.patch deleted file mode 100644 index 23e5f1e..0000000 --- a/CVE-2020-5260.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 10372307c11d0128c40d730418d3776f1a959ce3 Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Wed, 11 Mar 2020 17:53:41 -0400 -Subject: [PATCH] credential: avoid writing values with newlines - -The credential protocol that we use to speak to helpers can't represent -values with newlines in them. This was an intentional design choice to -keep the protocol simple, since none of the values we pass should -generally have newlines. - -However, if we _do_ encounter a newline in a value, we blindly transmit -it in credential_write(). Such values may break the protocol syntax, or -worse, inject new valid lines into the protocol stream. - -The most likely way for a newline to end up in a credential struct is by -decoding a URL with a percent-encoded newline. However, since the bug -occurs at the moment we write the value to the protocol, we'll catch it -there. That should leave no possibility of accidentally missing a code -path that can trigger the problem. - -At this level of the code we have little choice but to die(). However, -since we'd not ever expect to see this case outside of a malicious URL, -that's an acceptable outcome. - -Reported-by: Felix Wilhelm ---- - credential.c | 2 ++ - t/t0300-credentials.sh | 6 ++++++ - 2 files changed, 8 insertions(+) - -diff --git a/credential.c b/credential.c -index 62be651..a79aff0 100644 ---- a/credential.c -+++ b/credential.c -@@ -195,6 +195,8 @@ static void credential_write_item(FILE *fp, const char *key, const char *value) - { - if (!value) - return; -+ if (strchr(value, '\n')) -+ die("credential value for %s contains newline", key); - fprintf(fp, "%s=%s\n", key, value); - } - -diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh -index 82eaaea..26f3c3a 100755 ---- a/t/t0300-credentials.sh -+++ b/t/t0300-credentials.sh -@@ -308,4 +308,10 @@ test_expect_success 'empty helper spec resets helper list' ' - EOF - ' - -+test_expect_success 'url parser rejects embedded newlines' ' -+ test_must_fail git credential fill <<-\EOF -+ url=https://one.example.com?%0ahost=two.example.com/ -+ EOF -+' -+ - test_done --- -1.8.3.1 - diff --git a/credential-detect-unrepresentable-values-when-parsin.patch b/credential-detect-unrepresentable-values-when-parsin.patch deleted file mode 100644 index 7f1102a..0000000 --- a/credential-detect-unrepresentable-values-when-parsin.patch +++ /dev/null @@ -1,151 +0,0 @@ -From c716fe4bd917e013bf376a678b3a924447777b2d Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Thu, 12 Mar 2020 01:31:11 -0400 -Subject: [PATCH] credential: detect unrepresentable values when parsing urls - -The credential protocol can't represent newlines in values, but URLs can -embed percent-encoded newlines in various components. A previous commit -taught the low-level writing routines to die() when encountering this, -but we can be a little friendlier to the user by detecting them earlier -and handling them gracefully. - -This patch teaches credential_from_url() to notice such components, -issue a warning, and blank the credential (which will generally result -in prompting the user for a username and password). We blank the whole -credential in this case. Another option would be to blank only the -invalid component. However, we're probably better off not feeding a -partially-parsed URL result to a credential helper. We don't know how a -given helper would handle it, so we're better off to err on the side of -matching nothing rather than something unexpected. - -The die() call in credential_write() is _probably_ impossible to reach -after this patch. Values should end up in credential structs only by URL -parsing (which is covered here), or by reading credential protocol input -(which by definition cannot read a newline into a value). But we should -definitely keep the low-level check, as it's our final and most accurate -line of defense against protocol injection attacks. Arguably it could -become a BUG(), but it probably doesn't matter much either way. - -Note that the public interface of credential_from_url() grows a little -more than we need here. We'll use the extra flexibility in a future -patch to help fsck catch these cases. ---- - credential.c | 36 ++++++++++++++++++++++++++++++++++-- - credential.h | 16 ++++++++++++++++ - t/t0300-credentials.sh | 12 ++++++++++-- - 3 files changed, 60 insertions(+), 4 deletions(-) - -diff --git a/credential.c b/credential.c -index 00ee4d6..eeeac32 100644 ---- a/credential.c -+++ b/credential.c -@@ -321,7 +321,22 @@ void credential_reject(struct credential *c) - c->approved = 0; - } - --void credential_from_url(struct credential *c, const char *url) -+static int check_url_component(const char *url, int quiet, -+ const char *name, const char *value) -+{ -+ if (!value) -+ return 0; -+ if (!strchr(value, '\n')) -+ return 0; -+ -+ if (!quiet) -+ warning(_("url contains a newline in its %s component: %s"), -+ name, url); -+ return -1; -+} -+ -+int credential_from_url_gently(struct credential *c, const char *url, -+ int quiet) - { - const char *at, *colon, *cp, *slash, *host, *proto_end; - -@@ -335,7 +350,7 @@ void credential_from_url(struct credential *c, const char *url) - */ - proto_end = strstr(url, "://"); - if (!proto_end) -- return; -+ return 0; - cp = proto_end + 3; - at = strchr(cp, '@'); - colon = strchr(cp, ':'); -@@ -370,4 +385,21 @@ void credential_from_url(struct credential *c, const char *url) - while (p > c->path && *p == '/') - *p-- = '\0'; - } -+ -+ if (check_url_component(url, quiet, "username", c->username) < 0 || -+ check_url_component(url, quiet, "password", c->password) < 0 || -+ check_url_component(url, quiet, "protocol", c->protocol) < 0 || -+ check_url_component(url, quiet, "host", c->host) < 0 || -+ check_url_component(url, quiet, "path", c->path) < 0) -+ return -1; -+ -+ return 0; -+} -+ -+void credential_from_url(struct credential *c, const char *url) -+{ -+ if (credential_from_url_gently(c, url, 0) < 0) { -+ warning(_("skipping credential lookup for url: %s"), url); -+ credential_clear(c); -+ } - } -diff --git a/credential.h b/credential.h -index 6b0cd16..122a23c 100644 ---- a/credential.h -+++ b/credential.h -@@ -28,7 +28,23 @@ struct credential { - - int credential_read(struct credential *, FILE *); - void credential_write(const struct credential *, FILE *); -+ -+/* -+ * Parse a url into a credential struct, replacing any existing contents. -+ * -+ * Ifthe url can't be parsed (e.g., a missing "proto://" component), the -+ * resulting credential will be empty but we'll still return success from the -+ * "gently" form. -+ * -+ * If we encounter a component which cannot be represented as a credential -+ * value (e.g., because it contains a newline), the "gently" form will return -+ * an error but leave the broken state in the credential object for further -+ * examination. The non-gentle form will issue a warning to stderr and return -+ * an empty credential. -+ */ - void credential_from_url(struct credential *, const char *url); -+int credential_from_url_gently(struct credential *, const char *url, int quiet); -+ - int credential_match(const struct credential *have, - const struct credential *want); - -diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh -index 15cc3c5..3bec445 100755 ---- a/t/t0300-credentials.sh -+++ b/t/t0300-credentials.sh -@@ -309,9 +309,17 @@ test_expect_success 'empty helper spec resets helper list' ' - EOF - ' - --test_expect_success 'url parser rejects embedded newlines' ' -- test_must_fail git credential fill <<-\EOF -+test_expect_success 'url parser ignores embedded newlines' ' -+ check fill <<-EOF - url=https://one.example.com?%0ahost=two.example.com/ -+ -- -+ username=askpass-username -+ password=askpass-password -+ -- -+ warning: url contains a newline in its host component: https://one.example.com?%0ahost=two.example.com/ -+ warning: skipping credential lookup for url: https://one.example.com?%0ahost=two.example.com/ -+ askpass: Username: -+ askpass: Password: - EOF - ' - --- -1.8.3.1 - diff --git a/fast-import-delay-creating-leading-directories-for-e.patch b/fast-import-delay-creating-leading-directories-for-e.patch deleted file mode 100644 index d4b898d..0000000 --- a/fast-import-delay-creating-leading-directories-for-e.patch +++ /dev/null @@ -1,88 +0,0 @@ -From e5e484f5bb9690ac2aaab2d0ca23e7433b2ac8c0 Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Thu, 29 Aug 2019 13:33:48 -0400 -Subject: [PATCH 05/30] fast-import: delay creating leading directories for - export-marks - -When we parse the --export-marks option, we don't immediately open the -file, but we do create any leading directories. This can be especially -confusing when a command-line option overrides an in-stream one, in -which case we'd create the leading directory for the in-stream file, -even though we never actually write the file. - -Let's instead create the directories just before opening the file, which -means we'll create only useful directories. Note that this could change -the handling of relative paths if we chdir() in between, but we don't -actually do so; the only permanent chdir is from setup_git_directory() -which runs before either code path (potentially we should take the -pre-setup dir into account to avoid surprising the user, but that's an -orthogonal change). - -The test just adapts the existing "override" test to use paths with -leading directories. This checks both that the correct directory is -created (which worked before but was not tested), and that the -overridden one is not (our new fix here). - -While we're here, let's also check the error result of -safe_create_leading_directories(). We'd presumably notice any failure -immediately after when we try to open the file itself, but we can give a -more specific error message in this case. - -Signed-off-by: Jeff King ---- - fast-import.c | 7 ++++++- - t/t9300-fast-import.sh | 13 +++++++++++-- - 2 files changed, 17 insertions(+), 3 deletions(-) - -diff --git a/fast-import.c b/fast-import.c -index b05d560d0a..92e84d28a4 100644 ---- a/fast-import.c -+++ b/fast-import.c -@@ -1826,6 +1826,12 @@ static void dump_marks(void) - if (!export_marks_file || (import_marks_file && !import_marks_file_done)) - return; - -+ if (safe_create_leading_directories_const(export_marks_file)) { -+ failure |= error_errno("unable to create leading directories of %s", -+ export_marks_file); -+ return; -+ } -+ - if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) { - failure |= error_errno("Unable to write marks file %s", - export_marks_file); -@@ -3238,7 +3244,6 @@ static void option_active_branches(const char *branches) - static void option_export_marks(const char *marks) - { - export_marks_file = make_fast_import_path(marks); -- safe_create_leading_directories_const(export_marks_file); - } - - static void option_cat_blob_fd(const char *fd) -diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh -index f79fcf4c1e..f5f3e2cb71 100755 ---- a/t/t9300-fast-import.sh -+++ b/t/t9300-fast-import.sh -@@ -2132,8 +2132,17 @@ test_expect_success 'R: export-marks feature results in a marks file being creat - ' - - test_expect_success 'R: export-marks options can be overridden by commandline options' ' -- git fast-import --export-marks=other.marks input <<-\EOF && -+ feature export-marks=feature-sub/git.marks -+ blob -+ mark :1 -+ data 3 -+ hi -+ -+ EOF -+ git fast-import --export-marks=cmdline-sub/other.marks -Date: Thu, 29 Aug 2019 13:07:04 -0400 -Subject: [PATCH 04/30] fast-import: stop creating leading directories for - import-marks - -When asked to import marks from "subdir/file.marks", we create the -leading directory "subdir" if it doesn't exist. This makes no sense for -importing marks, where we only ever open the path for reading. - -Most of the time this would be a noop, since if the marks file exists, -then the leading directories exist, too. But if it doesn't (e.g., -because --import-marks-if-exists was used), then we'd create the useless -directory. - -This dates back to 580d5f83e7 (fast-import: always create marks_file -directories, 2010-03-29). Even then it was useless, so it seems to have -been added in error alongside the --export-marks case (which _is_ -helpful). - -Signed-off-by: Jeff King ---- - fast-import.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/fast-import.c b/fast-import.c -index 30b9479a75..b05d560d0a 100644 ---- a/fast-import.c -+++ b/fast-import.c -@@ -3198,7 +3198,6 @@ static void option_import_marks(const char *marks, - } - - import_marks_file = make_fast_import_path(marks); -- safe_create_leading_directories_const(import_marks_file); - import_marks_file_from_stream = from_stream; - import_marks_file_ignore_missing = ignore_missing; - } --- -2.17.1 - diff --git a/fast-import-tighten-parsing-of-boolean-command-line-.patch b/fast-import-tighten-parsing-of-boolean-command-line-.patch deleted file mode 100644 index 63955b5..0000000 --- a/fast-import-tighten-parsing-of-boolean-command-line-.patch +++ /dev/null @@ -1,39 +0,0 @@ -From a4d15d0cfb630844eb48a11f69ccaef9fa8719f4 Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Thu, 29 Aug 2019 11:25:45 -0400 -Subject: [PATCH 03/30] fast-import: tighten parsing of boolean command line - options - -We parse options like "--max-pack-size=" using skip_prefix(), which -makes sense to get at the bytes after the "=". However, we also parse -"--quiet" and "--stats" with skip_prefix(), which allows things like -"--quiet-nonsense" to behave like "--quiet". - -This was a mistaken conversion in 0f6927c229 (fast-import: put option -parsing code in separate functions, 2009-12-04). Let's tighten this to -an exact match, which was the original intent. - -Signed-off-by: Jeff King ---- - fast-import.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/fast-import.c b/fast-import.c -index 69886687ce..30b9479a75 100644 ---- a/fast-import.c -+++ b/fast-import.c -@@ -3282,9 +3282,9 @@ static int parse_one_option(const char *option) - option_active_branches(option); - } else if (skip_prefix(option, "export-pack-edges=", &option)) { - option_export_pack_edges(option); -- } else if (starts_with(option, "quiet")) { -+ } else if (!strcmp(option, "quiet")) { - show_stats = 0; -- } else if (starts_with(option, "stats")) { -+ } else if (!strcmp(option, "stats")) { - show_stats = 1; - } else { - return 0; --- -2.17.1 - diff --git a/fsck-detect-gitmodules-URLs-with-embedded-newlines.patch b/fsck-detect-gitmodules-URLs-with-embedded-newlines.patch deleted file mode 100644 index 6adad1f..0000000 --- a/fsck-detect-gitmodules-URLs-with-embedded-newlines.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 07259e74ec1237c836874342c65650bdee8a3993 Mon Sep 17 00:00:00 2001 -From: Jeff King -Date: Wed, 11 Mar 2020 18:48:24 -0400 -Subject: [PATCH] fsck: detect gitmodules URLs with embedded newlines - -The credential protocol can't handle values with newlines. We already -detect and block any such URLs from being used with credential helpers, -but let's also add an fsck check to detect and block gitmodules files -with such URLs. That will let us notice the problem earlier when -transfer.fsckObjects is turned on. And in particular it will prevent bad -objects from spreading, which may protect downstream users running older -versions of Git. - -We'll file this under the existing gitmodulesUrl flag, which covers URLs -with option injection. There's really no need to distinguish the exact -flaw in the URL in this context. Likewise, I've expanded the description -of t7416 to cover all types of bogus URLs. ---- - fsck.c | 16 +++++++++++++++- - t/t7416-submodule-dash-url.sh | 18 +++++++++++++++++- - 2 files changed, 32 insertions(+), 2 deletions(-) - -diff --git a/fsck.c b/fsck.c -index 0741e62..5b437c2 100644 ---- a/fsck.c -+++ b/fsck.c -@@ -14,6 +14,7 @@ - #include "packfile.h" - #include "submodule-config.h" - #include "config.h" -+#include "credential.h" - #include "help.h" - - static struct oidset gitmodules_found = OIDSET_INIT; -@@ -941,6 +942,19 @@ static int fsck_tag(struct tag *tag, const char *data, - return fsck_tag_buffer(tag, data, size, options); - } - -+static int check_submodule_url(const char *url) -+{ -+ struct credential c = CREDENTIAL_INIT; -+ int ret; -+ -+ if (looks_like_command_line_option(url)) -+ return -1; -+ -+ ret = credential_from_url_gently(&c, url, 1); -+ credential_clear(&c); -+ return ret; -+} -+ - struct fsck_gitmodules_data { - struct object *obj; - struct fsck_options *options; -@@ -965,7 +979,7 @@ static int fsck_gitmodules_fn(const char *var, const char *value, void *vdata) - "disallowed submodule name: %s", - name); - if (!strcmp(key, "url") && value && -- looks_like_command_line_option(value)) -+ check_submodule_url(value) < 0) - data->ret |= report(data->options, data->obj, - FSCK_MSG_GITMODULES_URL, - "disallowed submodule url: %s", -diff --git a/t/t7416-submodule-dash-url.sh b/t/t7416-submodule-dash-url.sh -index 5ba041f..41431b1 100755 ---- a/t/t7416-submodule-dash-url.sh -+++ b/t/t7416-submodule-dash-url.sh -@@ -1,6 +1,6 @@ - #!/bin/sh - --test_description='check handling of .gitmodule url with dash' -+test_description='check handling of disallowed .gitmodule urls' - . ./test-lib.sh - - test_expect_success 'create submodule with protected dash in url' ' -@@ -60,4 +60,20 @@ test_expect_success 'trailing backslash is handled correctly' ' - test_i18ngrep ! "unknown option" err - ' - -+test_expect_success 'fsck rejects embedded newline in url' ' -+ # create an orphan branch to avoid existing .gitmodules objects -+ git checkout --orphan newline && -+ cat >.gitmodules <<-\EOF && -+ [submodule "foo"] -+ url = "https://one.example.com?%0ahost=two.example.com/foo.git" -+ EOF -+ git add .gitmodules && -+ git commit -m "gitmodules with newline" && -+ test_when_finished "rm -rf dst" && -+ git init --bare dst && -+ git -C dst config transfer.fsckObjects true && -+ test_must_fail git push dst HEAD 2>err && -+ grep gitmodulesUrl err -+' -+ - test_done --- -1.8.3.1 - diff --git a/git-2.23.0.tar.sign b/git-2.23.0.tar.sign deleted file mode 100644 index e16b237b99ef38252addf347f37d51f78960dda0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 566 zcmV-60?GY}0y6{v0SEvc79j-T@HVmj=OQ1+cd8{JTS6B4-lz6xt5{Db3;gyAYN<&@i6Q;UtDiYs{!Fj_ zzdTw%>I8Pc^yJceL`%kUk7eoTJ!-s0`{7MA5dt0t^kaIbp?$8fQevr6$2dC}j#y$n z<+X$O`JMX3FlV^xG}5u{^Okx>Q+N(($ArNIIrb)74@vH}H?oxC?KS18* z4gqxE+5XnG5Ltg9s-|}04xrWrLf_BvB1algZ@9<7n0*vGlY9xO(i)jh;4vBcBE&Zx zh)*AaY^Z=KyLbs?&gKrRk5E!schiQ_-EKo+k9-tu+Tw7uUW0bm<>)+(WW1hhQDIhyYtGxJhkj4P1;1qtjw^prxazIHU_20jS9u<*K;I1oy`KSY z1u0lc8er*@lJZeC0noMtY6}Ztq`#`5hMU%}tO}}k3JkN^qGF-%uRRq0Nr1v3QMc6a zOxPs7DXtcR90<`jF>GjvFT38$$>m?XnD+3L6e~QikoWwCWH@wyDcy{|Pb@-?hh$Dp zH1V7r6NC$R^~03neKd*lo?dui+C|~f((Nn8HQEDOGvxhE^J77C^%bpU6LS+>%@Bjb+ diff --git a/git-2.27.0.tar.sign b/git-2.27.0.tar.sign new file mode 100644 index 0000000000000000000000000000000000000000..760ea5d546379514f2d7cfc85529e2103f87a812 GIT binary patch literal 566 zcmV-60?GY}0y6{v0SEvc79j-T@HVmj=OQ1+ci@5e6mp4e0CEudOvFs6934YRy8))tH{CGU*Uk!_!K6R8*)`&CaYSA(X7T88P2UUQxX3_RlcsS0)}taK?D0S8{t ze5604*Mq=Xr?rpiDZ4Y9Fnx7=EzeVV_As*FbIUpv&=5jquZP$V|8MFVbnu3rqTVNXe}%lwhe(4}T>{7$KEYbc_!Z6mZRQJ zqzUmo(_zrK9z~u$zJL}qqzkQm;pAL4>W)5#OaIz1Z4^8RXSi#RUR*t z-

J9mb@T_I<`Qy;4Pk{lqk3w}I?He}`PwsbH9RMaa7v1fy?aDmgxO7P%Lk>Z6tf zk(|=0g&&OA6$E_HgBt08(kM$J(d`dG7sy?E&8}T1sU#J(@rDaB{a#g(HbDQ!jkPV8 z_y;wgLOzb6eEC2SNGx#WCbf~teFY61J?M?}#^=4*yZwI9e;wBRt{p{xP=D?GE?|K> E7_zb!YybcN literal 0 HcmV?d00001 diff --git a/git-2.23.0.tar.xz b/git-2.27.0.tar.xz similarity index 42% rename from git-2.23.0.tar.xz rename to git-2.27.0.tar.xz index b28ddaebaa306246be4274ae4683c430cfbffd75..2c89c96f723f865995dd0e289ba0be2f23e1ad63 100644 GIT binary patch literal 6074636 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