From 5a8bcd3824a5dbc67d979f31cb9e95f9d48e333c Mon Sep 17 00:00:00 2001 From: Petr Stodulka Date: Thu, 19 Jan 2017 21:37:37 +0100 Subject: [PATCH 1/6] fix infinite loop of "git ls-tree" on broken symlink Resolves: #1414792 --- ...tree-with-broken-symlink-under-refs-.patch | 33 +++++++++ ...fe-limit-the-number-of-stat_ref-retr.patch | 74 +++++++++++++++++++ git.spec | 12 ++- 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 0001-Add-test-for-ls-tree-with-broken-symlink-under-refs-.patch create mode 100644 0002-resolve_ref_unsafe-limit-the-number-of-stat_ref-retr.patch diff --git a/0001-Add-test-for-ls-tree-with-broken-symlink-under-refs-.patch b/0001-Add-test-for-ls-tree-with-broken-symlink-under-refs-.patch new file mode 100644 index 0000000..d849084 --- /dev/null +++ b/0001-Add-test-for-ls-tree-with-broken-symlink-under-refs-.patch @@ -0,0 +1,33 @@ +From 45eb1ba86022558d71a9946ccbe173ba5d8f1e37 Mon Sep 17 00:00:00 2001 +From: Petr Stodulka +Date: Thu, 13 Oct 2016 13:23:47 +0200 +Subject: [PATCH 1/2] Add test for ls-tree with broken symlink under refs/heads + +git ls-tree goes into an infinite loop while serving pretty vanilla requests, +if the refs/heads/ directory contains a symlink that's broken. Added test +which check if git ends with expected exit code or timeout expires. +--- + t/t3103-ls-tree-misc.sh | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/t/t3103-ls-tree-misc.sh b/t/t3103-ls-tree-misc.sh +index 09dcf04..faf79c4 100755 +--- a/t/t3103-ls-tree-misc.sh ++++ b/t/t3103-ls-tree-misc.sh +@@ -21,4 +21,13 @@ test_expect_success 'ls-tree fails with non-zero exit code on broken tree' ' + test_must_fail git ls-tree -r HEAD + ' + ++test_expect_success 'ls-tree fails due to broken symlink instead of infinite loop' ' ++ mkdir foo_infinit && ++ cd foo_infinit && ++ git init testrepo && ++ cd testrepo && ++ mkdir -p .git/refs/remotes && ++ ln -s ../remotes/foo .git/refs/heads/bar && ++ test_expect_code 128 timeout 2 git ls-tree bar ++' + test_done +-- +2.5.5 + diff --git a/0002-resolve_ref_unsafe-limit-the-number-of-stat_ref-retr.patch b/0002-resolve_ref_unsafe-limit-the-number-of-stat_ref-retr.patch new file mode 100644 index 0000000..7a18808 --- /dev/null +++ b/0002-resolve_ref_unsafe-limit-the-number-of-stat_ref-retr.patch @@ -0,0 +1,74 @@ +From 5bc590cd3ce202243cd1c3ee22104bcb4f3b6c4e Mon Sep 17 00:00:00 2001 +From: Michael Haggerty +Date: Wed, 25 Mar 2015 22:33:11 +0100 +Subject: [PATCH 2/2] resolve_ref_unsafe(): limit the number of "stat_ref" + retries + +If there is a broken symlink where a loose reference file is expected, +then the attempt to open() it fails with ENOENT. This error is +misinterpreted to mean that the loose reference file itself has +disappeared due to a race, causing the lookup to be retried. But in +this scenario, the retries all suffer from the same problem, causing +an infinite loop. + +So put a limit (of 5) on the number of times that the stat_ref step +can be retried. + +Based-on-patch-by: Petr Stodulka +Signed-off-by: Michael Haggerty +--- + refs/files-backend.c | 6 ++++-- + refs/refs-internal.h | 6 ++++++ + 2 files changed, 10 insertions(+), 2 deletions(-) + +diff --git a/refs/files-backend.c b/refs/files-backend.c +index d16feb1..245a0b5 100644 +--- a/refs/files-backend.c ++++ b/refs/files-backend.c +@@ -1353,6 +1353,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, + int fd; + int ret = -1; + int save_errno; ++ int retries = 0; + + strbuf_reset(&sb_path); + strbuf_git_path(&sb_path, "%s", refname); +@@ -1390,7 +1391,8 @@ static int files_read_raw_ref(struct ref_store *ref_store, + if (S_ISLNK(st.st_mode)) { + strbuf_reset(&sb_contents); + if (strbuf_readlink(&sb_contents, path, 0) < 0) { +- if (errno == ENOENT || errno == EINVAL) ++ if ((errno == ENOENT || errno == EINVAL) && ++ retries++ < MAXRETRIES) + /* inconsistent with lstat; retry */ + goto stat_ref; + else +@@ -1426,7 +1428,7 @@ static int files_read_raw_ref(struct ref_store *ref_store, + */ + fd = open(path, O_RDONLY); + if (fd < 0) { +- if (errno == ENOENT) ++ if (errno == ENOENT && retries++ < MAXRETRIES) + /* inconsistent with lstat; retry */ + goto stat_ref; + else +diff --git a/refs/refs-internal.h b/refs/refs-internal.h +index 708b260..37e6b99 100644 +--- a/refs/refs-internal.h ++++ b/refs/refs-internal.h +@@ -255,6 +255,12 @@ int rename_ref_available(const char *old_refname, const char *new_refname); + /* We allow "recursive" symbolic refs. Only within reason, though */ + #define SYMREF_MAXDEPTH 5 + ++/* ++ * We allow only MAXRETRIES tries to jump on stat_ref, because of possible ++ * infinite loop ++ */ ++#define MAXRETRIES 5 ++ + /* Include broken references in a do_for_each_ref*() iteration: */ + #define DO_FOR_EACH_INCLUDE_BROKEN 0x01 + +-- +2.5.5 + diff --git a/git.spec b/git.spec index 6be42ab..a3b8192 100644 --- a/git.spec +++ b/git.spec @@ -55,7 +55,7 @@ Name: git Version: 2.9.3 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Fast Version Control System License: GPLv2 Group: Development/Tools @@ -92,6 +92,10 @@ Patch1: git-cvsimport-Ignore-cvsps-2.2b1-Branches-output.patch # https://bugzilla.redhat.com/600411 Patch3: git-1.7-el5-emacs-support.patch +# fix infinite loop + test +Patch4: 0001-Add-test-for-ls-tree-with-broken-symlink-under-refs-.patch +Patch5: 0002-resolve_ref_unsafe-limit-the-number-of-stat_ref-retr.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %if ! %{use_prebuilt_docs} && ! 0%{?_without_docs} @@ -376,6 +380,8 @@ rm -rf "$gpghome" # Cleanup tmp gpg home dir %if %{emacs_old} %patch3 -p1 %endif +%patch4 -p1 +%patch5 -p1 %if %{use_prebuilt_docs} mkdir -p prebuilt_docs/{html,man} @@ -736,6 +742,10 @@ rm -rf %{buildroot} # No files for you! %changelog +* Thu Jan 19 2017 Petr Stodulka -2.9.3-2 +- fix infinite loop of "git ls-tree" on broken symlink + Resolves: #1414792 + * Mon Aug 15 2016 Jon Ciesla - 2.9.3-1 - Update to 2.9.3. From 663c11a54890d6925a87b3bb6f683dacc5a06f44 Mon Sep 17 00:00:00 2001 From: Todd Zullinger Date: Tue, 4 Apr 2017 12:27:29 -0400 Subject: [PATCH 2/6] Apply upstream fix for blame segfault (#1438801) Upstream commit: https://github.com/git/git/commit/bc6b13a7d --- ...lame-fix-segfault-on-untracked-files.patch | 63 +++++++++++++++++++ git.spec | 10 ++- 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 0001-blame-fix-segfault-on-untracked-files.patch diff --git a/0001-blame-fix-segfault-on-untracked-files.patch b/0001-blame-fix-segfault-on-untracked-files.patch new file mode 100644 index 0000000..c985525 --- /dev/null +++ b/0001-blame-fix-segfault-on-untracked-files.patch @@ -0,0 +1,63 @@ +From bc6b13a7d2300e982dd3a3aeef2f3ad4d39cf149 Mon Sep 17 00:00:00 2001 +From: Thomas Gummerer +Date: Sat, 27 Aug 2016 21:01:50 +0100 +Subject: [PATCH] blame: fix segfault on untracked files + +Since 3b75ee9 ("blame: allow to blame paths freshly added to the index", +2016-07-16) git blame also looks at the index to determine if there is a +file that was freshly added to the index. + +cache_name_pos returns -pos - 1 in case there is no match is found, or +if the name matches, but the entry has a stage other than 0. As git +blame should work for unmerged files, it uses strcmp to determine +whether the name of the returned position matches, in which case the +file exists, but is merely unmerged, or if the file actually doesn't +exist in the index. + +If the repository is empty, or if the file would lexicographically be +sorted as the last file in the repository, -cache_name_pos - 1 is +outside of the length of the active_cache array, causing git blame to +segfault. Guard against that, and die() normally to restore the old +behaviour. + +Reported-by: Simon Ruderich +Signed-off-by: Thomas Gummerer +Signed-off-by: Junio C Hamano +--- + builtin/blame.c | 3 ++- + t/t8002-blame.sh | 5 +++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/builtin/blame.c b/builtin/blame.c +index 12c765acfe..4d52f9602e 100644 +--- a/builtin/blame.c ++++ b/builtin/blame.c +@@ -2245,7 +2245,8 @@ static void verify_working_tree_path(struct commit *work_tree, const char *path) + pos = cache_name_pos(path, strlen(path)); + if (pos >= 0) + ; /* path is in the index */ +- else if (!strcmp(active_cache[-1 - pos]->name, path)) ++ else if (-1 - pos < active_nr && ++ !strcmp(active_cache[-1 - pos]->name, path)) + ; /* path is in the index, unmerged */ + else + die("no such path '%s' in HEAD", path); +diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh +index ff09aced68..ab79de9544 100755 +--- a/t/t8002-blame.sh ++++ b/t/t8002-blame.sh +@@ -6,6 +6,11 @@ test_description='git blame' + PROG='git blame -c' + . "$TEST_DIRECTORY"/annotate-tests.sh + ++test_expect_success 'blame untracked file in empty repo' ' ++ >untracked && ++ test_must_fail git blame untracked ++' ++ + PROG='git blame -c -e' + test_expect_success 'blame --show-email' ' + check_count \ +-- +2.11.0 + diff --git a/git.spec b/git.spec index a3b8192..e9d2dc0 100644 --- a/git.spec +++ b/git.spec @@ -55,7 +55,7 @@ Name: git Version: 2.9.3 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Fast Version Control System License: GPLv2 Group: Development/Tools @@ -96,6 +96,10 @@ Patch3: git-1.7-el5-emacs-support.patch Patch4: 0001-Add-test-for-ls-tree-with-broken-symlink-under-refs-.patch Patch5: 0002-resolve_ref_unsafe-limit-the-number-of-stat_ref-retr.patch +# https://bugzilla.redhat.com/1438801 +# https://github.com/git/git/commit/bc6b13a7d +Patch6: 0001-blame-fix-segfault-on-untracked-files.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %if ! %{use_prebuilt_docs} && ! 0%{?_without_docs} @@ -382,6 +386,7 @@ rm -rf "$gpghome" # Cleanup tmp gpg home dir %endif %patch4 -p1 %patch5 -p1 +%patch6 -p1 %if %{use_prebuilt_docs} mkdir -p prebuilt_docs/{html,man} @@ -742,6 +747,9 @@ rm -rf %{buildroot} # No files for you! %changelog +* Tue Apr 04 2017 Todd Zullinger - 2.9.3-3 +- Apply upstream fix for blame segfault (#1438801) + * Thu Jan 19 2017 Petr Stodulka -2.9.3-2 - fix infinite loop of "git ls-tree" on broken symlink Resolves: #1414792 From b1b17a63f329b0ed590b92636d097aebf7d524ae Mon Sep 17 00:00:00 2001 From: Todd Zullinger Date: Tue, 9 May 2017 21:51:02 -0400 Subject: [PATCH 3/6] Update to 2.9.4 (resolves CVE-2017-8386) --- git.spec | 7 +++++-- sources | 12 ++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/git.spec b/git.spec index e9d2dc0..83d6dea 100644 --- a/git.spec +++ b/git.spec @@ -54,8 +54,8 @@ %endif Name: git -Version: 2.9.3 -Release: 3%{?dist} +Version: 2.9.4 +Release: 1%{?dist} Summary: Fast Version Control System License: GPLv2 Group: Development/Tools @@ -747,6 +747,9 @@ rm -rf %{buildroot} # No files for you! %changelog +* Tue May 09 2017 Todd Zullinger - 2.9.4-1 +- Update to 2.9.4 (resolves CVE-2017-8386) + * Tue Apr 04 2017 Todd Zullinger - 2.9.3-3 - Apply upstream fix for blame segfault (#1438801) diff --git a/sources b/sources index e0eb1b9..a74ec44 100644 --- a/sources +++ b/sources @@ -1,6 +1,6 @@ -316776336775d25d58888686a4893c86 git-2.9.3.tar.sign -3d32cb5cb5b4f29bd2eb1cde596fc542 git-2.9.3.tar.xz -cf0bf766505aa0674006dba6561c153b git-htmldocs-2.9.3.tar.sign -29378f5a360d86b9f5838ad74680accd git-htmldocs-2.9.3.tar.xz -1b7e97104f3f98cbae9fb475ab37aa19 git-manpages-2.9.3.tar.sign -337165a3b2bbe4814c73075cb6854ca2 git-manpages-2.9.3.tar.xz +SHA512 (git-2.9.4.tar.xz) = bb531df4c0f62df680095caf07ec66bbe29c4fc45f703cde37efe022c4ed427306339e0ab144ab53fa3f58dd34fe6371e9d374f33ebd985718a3b96026d97207 +SHA512 (git-2.9.4.tar.sign) = ba4dcdd3dcca55936e293293807f364fd5dcfcc65181247c7ddc09935e278fdc5bea2f2f8eb160b798fae180d48e0ee71e92f4bc6f09848450427bc26ead2b39 +SHA512 (git-htmldocs-2.9.4.tar.xz) = 6aca069f45f9ecd74102775552babf20e9fcb4e83796319f4a27f7a92f623a3f9ed99b946521409ac3cd9fc83835e04fac41f6d82d66b61e6301b92d594caafa +SHA512 (git-htmldocs-2.9.4.tar.sign) = 649449fd427b164cc1320c0d3f955d062334a76464a2a4cfe57e875cbcec4ace7670b2a07479be2516bf6ab0e16c50069879a8115c1aae489dacdd223fc5d89e +SHA512 (git-manpages-2.9.4.tar.xz) = 538bf93c9256b898397738f4e141760663a4ebf207d064256e8e1308e337175d86ea82395822a2c1af389a334867afa7e739db0d601e6bb324cef1b47fb46c27 +SHA512 (git-manpages-2.9.4.tar.sign) = ae6abfd8fd3e0292f6347741f43900c0d29aa0141bfe3cdceff1d27eb01541b3bd85e06b5fd5e918741bb668a49e36e8c300258080d9e50f83b4453fc0b6546c From f7391883e64651c9f2ae13a799c241510f7ec91f Mon Sep 17 00:00:00 2001 From: Todd Zullinger Date: Thu, 10 Aug 2017 17:47:48 -0400 Subject: [PATCH 4/6] Update to 2.9.5 (resolves CVE-2017-1000117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From the release announcement¹ A malicious third-party can give a crafted "ssh://..." URL to an unsuspecting victim, and an attempt to visit the URL can result in any program that exists on the victim's machine being executed. Such a URL could be placed in the .gitmodules file of a malicious project, and an unsuspecting victim could be tricked into running "git clone --recurse-submodules" to trigger the vulnerability. Credits to find and fix the issue go to Brian Neel at GitLab, Joern Schneeweisz of Recurity Labs and Jeff King at GitHub. ¹ https://public-inbox.org/git/xmqqh8xf482j.fsf@gitster.mtv.corp.google.com/ --- git.spec | 5 ++++- sources | 12 ++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/git.spec b/git.spec index 83d6dea..11cca49 100644 --- a/git.spec +++ b/git.spec @@ -54,7 +54,7 @@ %endif Name: git -Version: 2.9.4 +Version: 2.9.5 Release: 1%{?dist} Summary: Fast Version Control System License: GPLv2 @@ -747,6 +747,9 @@ rm -rf %{buildroot} # No files for you! %changelog +* Thu Aug 10 2017 Todd Zullinger - 2.9.5-1 +- Update to 2.9.5 (resolves CVE-2017-1000117) + * Tue May 09 2017 Todd Zullinger - 2.9.4-1 - Update to 2.9.4 (resolves CVE-2017-8386) diff --git a/sources b/sources index a74ec44..3fd647f 100644 --- a/sources +++ b/sources @@ -1,6 +1,6 @@ -SHA512 (git-2.9.4.tar.xz) = bb531df4c0f62df680095caf07ec66bbe29c4fc45f703cde37efe022c4ed427306339e0ab144ab53fa3f58dd34fe6371e9d374f33ebd985718a3b96026d97207 -SHA512 (git-2.9.4.tar.sign) = ba4dcdd3dcca55936e293293807f364fd5dcfcc65181247c7ddc09935e278fdc5bea2f2f8eb160b798fae180d48e0ee71e92f4bc6f09848450427bc26ead2b39 -SHA512 (git-htmldocs-2.9.4.tar.xz) = 6aca069f45f9ecd74102775552babf20e9fcb4e83796319f4a27f7a92f623a3f9ed99b946521409ac3cd9fc83835e04fac41f6d82d66b61e6301b92d594caafa -SHA512 (git-htmldocs-2.9.4.tar.sign) = 649449fd427b164cc1320c0d3f955d062334a76464a2a4cfe57e875cbcec4ace7670b2a07479be2516bf6ab0e16c50069879a8115c1aae489dacdd223fc5d89e -SHA512 (git-manpages-2.9.4.tar.xz) = 538bf93c9256b898397738f4e141760663a4ebf207d064256e8e1308e337175d86ea82395822a2c1af389a334867afa7e739db0d601e6bb324cef1b47fb46c27 -SHA512 (git-manpages-2.9.4.tar.sign) = ae6abfd8fd3e0292f6347741f43900c0d29aa0141bfe3cdceff1d27eb01541b3bd85e06b5fd5e918741bb668a49e36e8c300258080d9e50f83b4453fc0b6546c +SHA512 (git-2.9.5.tar.xz) = 5a3f62b9640a477bfd1a299f365ddb36c69ce5fb92ecf3ba7176686836a3057de7c74078b46526abd7bee0204c49e36bbd7d77d4c2f69c6524eca592ab6c365d +SHA512 (git-2.9.5.tar.sign) = ae799e503c9648fffd9c18ce7bf826f8e28cec2bce196f67275f49eeba3c250457c2a4aa8316079e43f06a6374bbc2c3cc196555f58452aecef8be8727b2edcd +SHA512 (git-htmldocs-2.9.5.tar.xz) = 8ac48cc1bd9635ede960fb2dc5e18590fa0c743e0892e754cade2b5b2833a24f463059f2992e74a281b5ae3ff48309187d06f2e546676ceb3c38cf5ef32fb555 +SHA512 (git-htmldocs-2.9.5.tar.sign) = 9239fda9b02adf4232048d259fe133cf67999836e3bb9ea76e96b18721916af5b22b375afbd857cfbb49dbafd9a9b8e1a02b0e53d21ecf04f2e5831a6b9fcdea +SHA512 (git-manpages-2.9.5.tar.xz) = e4daa7b481c1e14da76dac04348843240c9ece80123f6e6e10835d74737605c03ca07c60b90b94f59ba5fc91b2608115db632f3636a6eec6c95df682191ea9fb +SHA512 (git-manpages-2.9.5.tar.sign) = 48f9395ea09200275fe9836f27bfea1672151b351ae79a6554d9817d72e97d0db8d4656079bd1af3eeb2fda2c1d7e0ec9ce3f16b0fc3dda659cfd6fc836c6495 From a958e0ad2acc25094a622459e73c23a192dc11ad Mon Sep 17 00:00:00 2001 From: Todd Zullinger Date: Tue, 26 Sep 2017 10:28:22 -0400 Subject: [PATCH 5/6] Cherry-pick patch set to harden git shell and git cvsserver Harden "git shell" against an unsafe user input, which "git cvsserver" copes with poorly. References: http://seclists.org/oss-sec/2017/q3/534 https://public-inbox.org/git/xmqqy3p29ekj.fsf@gitster.mtv.corp.google.com/ --- ....5-git-shell-and-cvsserver-hardening.patch | 518 ++++++++++++++++++ git.spec | 9 +- 2 files changed, 526 insertions(+), 1 deletion(-) create mode 100644 git-2.9.5-git-shell-and-cvsserver-hardening.patch diff --git a/git-2.9.5-git-shell-and-cvsserver-hardening.patch b/git-2.9.5-git-shell-and-cvsserver-hardening.patch new file mode 100644 index 0000000..85a8b92 --- /dev/null +++ b/git-2.9.5-git-shell-and-cvsserver-hardening.patch @@ -0,0 +1,518 @@ +From 9a1c497f7f3fbbd21673a6023871b891a6225ebe Mon Sep 17 00:00:00 2001 +From: Junio C Hamano +Date: Mon, 11 Sep 2017 14:44:24 +0900 +Subject: [PATCH 1/6] cvsserver: move safe_pipe_capture() to the main package + +As a preparation for replacing `command` with a call to this +function from outside GITCVS::updater package, move it to the main +package. + +Signed-off-by: Junio C Hamano +(cherry picked from commit fce13af5d20cad8dcb2d0e47bcf01b6960f08e55) +--- + git-cvsserver.perl | 47 ++++++++++++++++++++++------------------------- + 1 file changed, 22 insertions(+), 25 deletions(-) + +diff --git a/git-cvsserver.perl b/git-cvsserver.perl +index d50c85ed7b..8229d9d198 100755 +--- a/git-cvsserver.perl ++++ b/git-cvsserver.perl +@@ -3406,6 +3406,22 @@ sub refHashEqual + return $out; + } + ++# an alternative to `command` that allows input to be passed as an array ++# to work around shell problems with weird characters in arguments ++ ++sub safe_pipe_capture { ++ ++ my @output; ++ ++ if (my $pid = open my $child, '-|') { ++ @output = (<$child>); ++ close $child or die join(' ',@_).": $! $?"; ++ } else { ++ exec(@_) or die "$! $?"; # exec() can fail the executable can't be found ++ } ++ return wantarray ? @output : join('',@output); ++} ++ + + package GITCVS::log; + +@@ -3882,7 +3898,7 @@ sub update + # several candidate merge bases. let's assume + # that the first one is the best one. + my $base = eval { +- safe_pipe_capture('git', 'merge-base', ++ ::safe_pipe_capture('git', 'merge-base', + $lastpicked, $parent); + }; + # The two branches may not be related at all, +@@ -4749,7 +4765,7 @@ sub getMetaFromCommithash + return $retVal; + } + +- my($fileHash)=safe_pipe_capture("git","rev-parse","$revCommit:$filename"); ++ my($fileHash) = ::safe_pipe_capture("git","rev-parse","$revCommit:$filename"); + chomp $fileHash; + if(!($fileHash=~/^[0-9a-f]{40}$/)) + { +@@ -4844,8 +4860,8 @@ sub lookupCommitRef + return $commitHash; + } + +- $commitHash=safe_pipe_capture("git","rev-parse","--verify","--quiet", +- $self->unescapeRefName($ref)); ++ $commitHash = ::safe_pipe_capture("git","rev-parse","--verify","--quiet", ++ $self->unescapeRefName($ref)); + $commitHash=~s/\s*$//; + if(!($commitHash=~/^[0-9a-f]{40}$/)) + { +@@ -4854,7 +4870,7 @@ sub lookupCommitRef + + if( defined($commitHash) ) + { +- my $type=safe_pipe_capture("git","cat-file","-t",$commitHash); ++ my $type = ::safe_pipe_capture("git","cat-file","-t",$commitHash); + if( ! ($type=~/^commit\s*$/ ) ) + { + $commitHash=undef; +@@ -4907,7 +4923,7 @@ sub commitmessage + return $message; + } + +- my @lines = safe_pipe_capture("git", "cat-file", "commit", $commithash); ++ my @lines = ::safe_pipe_capture("git", "cat-file", "commit", $commithash); + shift @lines while ( $lines[0] =~ /\S/ ); + $message = join("",@lines); + $message .= " " if ( $message =~ /\n$/ ); +@@ -5056,25 +5072,6 @@ sub in_array + return $retval; + } + +-=head2 safe_pipe_capture +- +-an alternative to `command` that allows input to be passed as an array +-to work around shell problems with weird characters in arguments +- +-=cut +-sub safe_pipe_capture { +- +- my @output; +- +- if (my $pid = open my $child, '-|') { +- @output = (<$child>); +- close $child or die join(' ',@_).": $! $?"; +- } else { +- exec(@_) or die "$! $?"; # exec() can fail the executable can't be found +- } +- return wantarray ? @output : join('',@output); +-} +- + =head2 mangle_dirname + + create a string from a directory name that is suitable to use as +-- +2.14.1 + + +From a871ec30ae5d7b472b35641a2a1b35685b6d41bb Mon Sep 17 00:00:00 2001 +From: joernchen +Date: Mon, 11 Sep 2017 14:45:09 +0900 +Subject: [PATCH 2/6] cvsserver: use safe_pipe_capture instead of backticks + +This makes the script pass arguments that are derived from end-user +input in safer way when invoking subcommands. + +Reported-by: joernchen +Signed-off-by: joernchen +Signed-off-by: Junio C Hamano +(cherry picked from commit 27dd73871f814062737c327103ee43f1eb7f30d9) +--- + git-cvsserver.perl | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +diff --git a/git-cvsserver.perl b/git-cvsserver.perl +index 8229d9d198..bd29b26cc2 100755 +--- a/git-cvsserver.perl ++++ b/git-cvsserver.perl +@@ -841,7 +841,7 @@ sub req_Modified + # Save the file data in $state + $state->{entries}{$state->{directory}.$data}{modified_filename} = $filename; + $state->{entries}{$state->{directory}.$data}{modified_mode} = $mode; +- $state->{entries}{$state->{directory}.$data}{modified_hash} = `git hash-object $filename`; ++ $state->{entries}{$state->{directory}.$data}{modified_hash} = safe_pipe_capture('git','hash-object',$filename); + $state->{entries}{$state->{directory}.$data}{modified_hash} =~ s/\s.*$//s; + + #$log->debug("req_Modified : file=$data mode=$mode size=$size"); +@@ -1463,7 +1463,7 @@ sub req_update + # transmit file, format is single integer on a line by itself (file + # size) followed by the file contents + # TODO : we should copy files in blocks +- my $data = `cat $mergedFile`; ++ my $data = safe_pipe_capture('cat', $mergedFile); + $log->debug("File size : " . length($data)); + print length($data) . "\n"; + print $data; +@@ -1579,7 +1579,7 @@ sub req_ci + $branchRef = "refs/heads/$stickyInfo->{tag}"; + } + +- $parenthash = `git show-ref -s $branchRef`; ++ $parenthash = safe_pipe_capture('git', 'show-ref', '-s', $branchRef); + chomp $parenthash; + if ($parenthash !~ /^[0-9a-f]{40}$/) + { +@@ -1704,7 +1704,7 @@ sub req_ci + } + close $msg_fh; + +- my $commithash = `git commit-tree $treehash -p $parenthash < $msg_filename`; ++ my $commithash = safe_pipe_capture('git', 'commit-tree', $treehash, '-p', $parenthash, '-F', $msg_filename); + chomp($commithash); + $log->info("Commit hash : $commithash"); + +@@ -2854,12 +2854,12 @@ sub transmitfile + + die "Need filehash" unless ( defined ( $filehash ) and $filehash =~ /^[a-zA-Z0-9]{40}$/ ); + +- my $type = `git cat-file -t $filehash`; ++ my $type = safe_pipe_capture('git', 'cat-file', '-t', $filehash); + chomp $type; + + die ( "Invalid type '$type' (expected 'blob')" ) unless ( defined ( $type ) and $type eq "blob" ); + +- my $size = `git cat-file -s $filehash`; ++ my $size = safe_pipe_capture('git', 'cat-file', '-s', $filehash); + chomp $size; + + $log->debug("transmitfile($filehash) size=$size, type=$type"); +@@ -3040,7 +3040,7 @@ sub ensureWorkTree + chdir $work->{emptyDir} or + die "Unable to chdir to $work->{emptyDir}\n"; + +- my $ver = `git show-ref -s refs/heads/$state->{module}`; ++ my $ver = safe_pipe_capture('git', 'show-ref', '-s', "refs/heads/$state->{module}"); + chomp $ver; + if ($ver !~ /^[0-9a-f]{40}$/) + { +@@ -3287,7 +3287,7 @@ sub open_blob_or_die + die "Need filehash\n"; + } + +- my $type = `git cat-file -t $name`; ++ my $type = safe_pipe_capture('git', 'cat-file', '-t', $name); + chomp $type; + + unless ( defined ( $type ) and $type eq "blob" ) +@@ -3296,7 +3296,7 @@ sub open_blob_or_die + die ( "Invalid type '$type' (expected 'blob')" ) + } + +- my $size = `git cat-file -s $name`; ++ my $size = safe_pipe_capture('git', 'cat-file', '-s', $name); + chomp $size; + + $log->debug("open_blob_or_die($name) size=$size, type=$type"); +@@ -3813,10 +3813,10 @@ sub update + # first lets get the commit list + $ENV{GIT_DIR} = $self->{git_path}; + +- my $commitsha1 = `git rev-parse $self->{module}`; ++ my $commitsha1 = ::safe_pipe_capture('git', 'rev-parse', $self->{module}); + chomp $commitsha1; + +- my $commitinfo = `git cat-file commit $self->{module} 2>&1`; ++ my $commitinfo = ::safe_pipe_capture('git', 'cat-file', 'commit', $self->{module}); + unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{40}/ ) + { + die("Invalid module '$self->{module}'"); +-- +2.14.1 + + +From d213a1c065b12601e3147363f6e0b11d85f5d514 Mon Sep 17 00:00:00 2001 +From: Junio C Hamano +Date: Mon, 11 Sep 2017 14:45:54 +0900 +Subject: [PATCH 3/6] cvsserver: use safe_pipe_capture for `constant commands` + as well + +This is not strictly necessary, but it is a good code hygiene. + +Signed-off-by: Junio C Hamano +(cherry picked from commit 46203ac24dc7e6b5a8d4f1b024ed93591705d47b) +--- + git-cvsserver.perl | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/git-cvsserver.perl b/git-cvsserver.perl +index bd29b26cc2..ae1044273d 100755 +--- a/git-cvsserver.perl ++++ b/git-cvsserver.perl +@@ -356,7 +356,7 @@ sub req_Root + return 0; + } + +- my @gitvars = `git config -l`; ++ my @gitvars = safe_pipe_capture(qw(git config -l)); + if ($?) { + print "E problems executing git-config on the server -- this is not a git repository or the PATH is not set correctly.\n"; + print "E \n"; +@@ -943,7 +943,7 @@ sub req_co + + # Provide list of modules, if -c was used. + if (exists $state->{opt}{c}) { +- my $showref = `git show-ref --heads`; ++ my $showref = safe_pipe_capture(qw(git show-ref --heads)); + for my $line (split '\n', $showref) { + if ( $line =~ m% refs/heads/(.*)$% ) { + print "M $1\t$1\n"; +@@ -1181,7 +1181,7 @@ sub req_update + # projects (heads in this case) to checkout. + # + if ($state->{module} eq '') { +- my $showref = `git show-ref --heads`; ++ my $showref = safe_pipe_capture(qw(git show-ref --heads)); + print "E cvs update: Updating .\n"; + for my $line (split '\n', $showref) { + if ( $line =~ m% refs/heads/(.*)$% ) { +@@ -1687,7 +1687,7 @@ sub req_ci + return; + } + +- my $treehash = `git write-tree`; ++ my $treehash = safe_pipe_capture(qw(git write-tree)); + chomp $treehash; + + $log->debug("Treehash : $treehash, Parenthash : $parenthash"); +-- +2.14.1 + + +From 7b1cfcc88d29d28133f6864c9ef7173d1edffa60 Mon Sep 17 00:00:00 2001 +From: Jeff King +Date: Mon, 11 Sep 2017 11:27:51 -0400 +Subject: [PATCH 4/6] shell: drop git-cvsserver support by default + +The git-cvsserver script is old and largely unmaintained +these days. But git-shell allows untrusted users to run it +out of the box, significantly increasing its attack surface. + +Let's drop it from git-shell's list of internal handlers so +that it cannot be run by default. This is not backwards +compatible. But given the age and development activity on +CVS-related parts of Git, this is likely to impact very few +users, while helping many more (i.e., anybody who runs +git-shell and had no intention of supporting CVS). + +There's no configuration mechanism in git-shell for us to +add a boolean and flip it to "off". But there is a mechanism +for adding custom commands, and adding CVS support here is +fairly trivial. Let's document it to give guidance to +anybody who really is still running cvsserver. + +Signed-off-by: Jeff King +Signed-off-by: Junio C Hamano +(cherry picked from commit 9a42c03cb71eaa9d41ba67275de38c997a791c32) +--- + Documentation/git-shell.txt | 16 ++++++++++++++ + shell.c | 14 ------------ + t/t9400-git-cvsserver-server.sh | 48 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 64 insertions(+), 14 deletions(-) + +diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt +index 2e30a3e42d..54cf2560be 100644 +--- a/Documentation/git-shell.txt ++++ b/Documentation/git-shell.txt +@@ -79,6 +79,22 @@ EOF + $ chmod +x $HOME/git-shell-commands/no-interactive-login + ---------------- + ++To enable git-cvsserver access (which should generally have the ++`no-interactive-login` example above as a prerequisite, as creating ++the git-shell-commands directory allows interactive logins): ++ ++---------------- ++$ cat >$HOME/git-shell-commands/cvs <<\EOF ++if ! test $# = 1 && test "$1" = "server" ++then ++ echo >&2 "git-cvsserver only handles \"server\"" ++ exit 1 ++fi ++exec git cvsserver server ++EOF ++$ chmod +x $HOME/git-shell-commands/cvs ++---------------- ++ + SEE ALSO + -------- + ssh(1), +diff --git a/shell.c b/shell.c +index fe2d314593..234b2d4f16 100644 +--- a/shell.c ++++ b/shell.c +@@ -25,19 +25,6 @@ static int do_generic_cmd(const char *me, char *arg) + return execv_git_cmd(my_argv); + } + +-static int do_cvs_cmd(const char *me, char *arg) +-{ +- const char *cvsserver_argv[3] = { +- "cvsserver", "server", NULL +- }; +- +- if (!arg || strcmp(arg, "server")) +- die("git-cvsserver only handles server: %s", arg); +- +- setup_path(); +- return execv_git_cmd(cvsserver_argv); +-} +- + static int is_valid_cmd_name(const char *cmd) + { + /* Test command contains no . or / characters */ +@@ -134,7 +121,6 @@ static struct commands { + { "git-receive-pack", do_generic_cmd }, + { "git-upload-pack", do_generic_cmd }, + { "git-upload-archive", do_generic_cmd }, +- { "cvs", do_cvs_cmd }, + { NULL }, + }; + +diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh +index 432c61d246..c30660d606 100755 +--- a/t/t9400-git-cvsserver-server.sh ++++ b/t/t9400-git-cvsserver-server.sh +@@ -588,4 +588,52 @@ test_expect_success 'cvs annotate' ' + test_cmp ../expect ../actual + ' + ++#------------ ++# running via git-shell ++#------------ ++ ++cd "$WORKDIR" ++ ++test_expect_success 'create remote-cvs helper' ' ++ write_script remote-cvs <<-\EOF ++ exec git shell -c "cvs server" ++ EOF ++' ++ ++test_expect_success 'cvs server does not run with vanilla git-shell' ' ++ ( ++ cd cvswork && ++ CVS_SERVER=$WORKDIR/remote-cvs && ++ export CVS_SERVER && ++ test_must_fail cvs log merge ++ ) ++' ++ ++test_expect_success 'configure git shell to run cvs server' ' ++ mkdir "$HOME"/git-shell-commands && ++ ++ write_script "$HOME"/git-shell-commands/cvs <<-\EOF && ++ if ! test $# = 1 && test "$1" = "server" ++ then ++ echo >&2 "git-cvsserver only handles \"server\"" ++ exit 1 ++ fi ++ exec git cvsserver server ++ EOF ++ ++ # Should not be used, but part of the recommended setup ++ write_script "$HOME"/git-shell-commands/no-interactive-login <<-\EOF ++ echo Interactive login forbidden ++ EOF ++' ++ ++test_expect_success 'cvs server can run with recommended config' ' ++ ( ++ cd cvswork && ++ CVS_SERVER=$WORKDIR/remote-cvs && ++ export CVS_SERVER && ++ cvs log merge ++ ) ++' ++ + test_done +-- +2.14.1 + + +From 974a1f5703091e07891cfb743c50cb66634ef8cf Mon Sep 17 00:00:00 2001 +From: Jeff King +Date: Mon, 11 Sep 2017 10:24:11 -0400 +Subject: [PATCH 5/6] archimport: use safe_pipe_capture for user input + +Refnames can contain shell metacharacters which need to be +passed verbatim to sub-processes. Using safe_pipe_capture +skips the shell entirely. + +Signed-off-by: Jeff King +Signed-off-by: Junio C Hamano +(cherry picked from commit 8d0fad0a7a6ba34fd706c148fa7ed1f8eb2b8b26) +--- + git-archimport.perl | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/git-archimport.perl b/git-archimport.perl +index 9cb123a07d..b7c173c345 100755 +--- a/git-archimport.perl ++++ b/git-archimport.perl +@@ -983,7 +983,7 @@ sub find_parents { + # check that we actually know about the branch + next unless -e "$git_dir/refs/heads/$branch"; + +- my $mergebase = `git-merge-base $branch $ps->{branch}`; ++ my $mergebase = safe_pipe_capture(qw(git-merge-base), $branch, $ps->{branch}); + if ($?) { + # Don't die here, Arch supports one-way cherry-picking + # between branches with no common base (or any relationship +@@ -1074,7 +1074,7 @@ sub find_parents { + + sub git_rev_parse { + my $name = shift; +- my $val = `git-rev-parse $name`; ++ my $val = safe_pipe_capture(qw(git-rev-parse), $name); + die "Error: git-rev-parse $name" if $?; + chomp $val; + return $val; +-- +2.14.1 + + +From c6d8647e2857f1ffbe1c6ff0c006b8da0710f9d4 Mon Sep 17 00:00:00 2001 +From: Jeff King +Date: Mon, 11 Sep 2017 10:24:26 -0400 +Subject: [PATCH 6/6] cvsimport: shell-quote variable used in backticks + +We run `git rev-parse` though the shell, and quote its +argument only with single-quotes. This prevents most +metacharacters from being a problem, but misses the obvious +case when $name itself has single-quotes in it. We can fix +this by applying the usual shell-quoting formula. + +Signed-off-by: Jeff King +Signed-off-by: Junio C Hamano +(cherry picked from commit 5b4efea666951efe0770f8d5a301f8917015315f) +--- + git-cvsimport.perl | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/git-cvsimport.perl b/git-cvsimport.perl +index 1e4e65a45d..36929921ea 100755 +--- a/git-cvsimport.perl ++++ b/git-cvsimport.perl +@@ -642,6 +642,7 @@ sub is_sha1 { + + sub get_headref ($) { + my $name = shift; ++ $name =~ s/'/'\\''/; + my $r = `git rev-parse --verify '$name' 2>/dev/null`; + return undef unless $? == 0; + chomp $r; +-- +2.14.1 + diff --git a/git.spec b/git.spec index 11cca49..193d914 100644 --- a/git.spec +++ b/git.spec @@ -55,7 +55,7 @@ Name: git Version: 2.9.5 -Release: 1%{?dist} +Release: 2%{?dist} Summary: Fast Version Control System License: GPLv2 Group: Development/Tools @@ -100,6 +100,9 @@ Patch5: 0002-resolve_ref_unsafe-limit-the-number-of-stat_ref-retr.patch # https://github.com/git/git/commit/bc6b13a7d Patch6: 0001-blame-fix-segfault-on-untracked-files.patch +# Cherry-picked patch set from 2.10.5 to harden git shell and git cvsserver +Patch7: git-2.9.5-git-shell-and-cvsserver-hardening.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %if ! %{use_prebuilt_docs} && ! 0%{?_without_docs} @@ -387,6 +390,7 @@ rm -rf "$gpghome" # Cleanup tmp gpg home dir %patch4 -p1 %patch5 -p1 %patch6 -p1 +%patch7 -p1 %if %{use_prebuilt_docs} mkdir -p prebuilt_docs/{html,man} @@ -747,6 +751,9 @@ rm -rf %{buildroot} # No files for you! %changelog +* Tue Sep 26 2017 Todd Zullinger - 2.9.5-2 +- Cherry-pick patch set to harden git shell and git cvsserver + * Thu Aug 10 2017 Todd Zullinger - 2.9.5-1 - Update to 2.9.5 (resolves CVE-2017-1000117) From 1e50591a09e8bebd3b6b46d1c0b1d32237db4b12 Mon Sep 17 00:00:00 2001 From: Todd Zullinger Date: Tue, 7 Nov 2017 11:55:56 -0500 Subject: [PATCH 6/6] Fix git clone memory exhaustion (CVE-2017-15298) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick upstream patch from a937b37e76 (revision: quit pruning diff more quickly when possible, 2017-10-13)¹. Resolves: #1510455, #1510457 ¹ https://github.com/git/git/commit/a937b37e76 --- ...uning-diff-more-quickly-when-possibl.patch | 129 ++++++++++++++++++ git.spec | 11 +- 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 0001-revision-quit-pruning-diff-more-quickly-when-possibl.patch diff --git a/0001-revision-quit-pruning-diff-more-quickly-when-possibl.patch b/0001-revision-quit-pruning-diff-more-quickly-when-possibl.patch new file mode 100644 index 0000000..1bce6af --- /dev/null +++ b/0001-revision-quit-pruning-diff-more-quickly-when-possibl.patch @@ -0,0 +1,129 @@ +From 0523d90a901e5cb6116e725f02c7f80a444405b6 Mon Sep 17 00:00:00 2001 +From: Jeff King +Date: Fri, 13 Oct 2017 11:27:45 -0400 +Subject: [PATCH] revision: quit pruning diff more quickly when possible + +When the revision traversal machinery is given a pathspec, +we must compute the parent-diff for each commit to determine +which ones are TREESAME. We set the QUICK diff flag to avoid +looking at more entries than we need; we really just care +whether there are any changes at all. + +But there is one case where we want to know a bit more: if +--remove-empty is set, we care about finding cases where the +change consists only of added entries (in which case we may +prune the parent in try_to_simplify_commit()). To cover that +case, our file_add_remove() callback does not quit the diff +upon seeing an added entry; it keeps looking for other types +of entries. + +But this means when --remove-empty is not set (and it is not +by default), we compute more of the diff than is necessary. +You can see this in a pathological case where a commit adds +a very large number of entries, and we limit based on a +broad pathspec. E.g.: + + perl -e ' + chomp(my $blob = `git hash-object -w --stdin remove_empty_trees. This callback parameter could be +passed to the "add_remove" and "change" callbacks, but +there's not much point. They already receive the +diff_options struct, and doing it this way avoids having to +update the function signature of the other callbacks +(arguably the format_callback and output_prefix functions +could benefit from the same simplification). + +Signed-off-by: Jeff King +Signed-off-by: Junio C Hamano +(cherry picked from commit a937b37e766479c8e780b17cce9c4b252fd97e40) +--- + diff.h | 1 + + revision.c | 16 +++++++++++++--- + 2 files changed, 14 insertions(+), 3 deletions(-) + +diff --git a/diff.h b/diff.h +index 125447be09..e37d93ec0a 100644 +--- a/diff.h ++++ b/diff.h +@@ -171,6 +171,7 @@ struct diff_options { + pathchange_fn_t pathchange; + change_fn_t change; + add_remove_fn_t add_remove; ++ void *change_fn_data; + diff_format_fn_t format_callback; + void *format_callback_data; + diff_prefix_fn_t output_prefix; +diff --git a/revision.c b/revision.c +index fe0f3a4f41..361ae5eb16 100644 +--- a/revision.c ++++ b/revision.c +@@ -394,8 +394,16 @@ static struct commit *one_relevant_parent(const struct rev_info *revs, + * if the whole diff is removal of old data, and otherwise + * REV_TREE_DIFFERENT (of course if the trees are the same we + * want REV_TREE_SAME). +- * That means that once we get to REV_TREE_DIFFERENT, we do not +- * have to look any further. ++ * ++ * The only time we care about the distinction is when ++ * remove_empty_trees is in effect, in which case we care only about ++ * whether the whole change is REV_TREE_NEW, or if there's another type ++ * of change. Which means we can stop the diff early in either of these ++ * cases: ++ * ++ * 1. We're not using remove_empty_trees at all. ++ * ++ * 2. We saw anything except REV_TREE_NEW. + */ + static int tree_difference = REV_TREE_SAME; + +@@ -406,9 +414,10 @@ static void file_add_remove(struct diff_options *options, + const char *fullpath, unsigned dirty_submodule) + { + int diff = addremove == '+' ? REV_TREE_NEW : REV_TREE_OLD; ++ struct rev_info *revs = options->change_fn_data; + + tree_difference |= diff; +- if (tree_difference == REV_TREE_DIFFERENT) ++ if (!revs->remove_empty_trees || tree_difference != REV_TREE_NEW) + DIFF_OPT_SET(options, HAS_CHANGES); + } + +@@ -1348,6 +1357,7 @@ void init_revisions(struct rev_info *revs, const char *prefix) + DIFF_OPT_SET(&revs->pruning, QUICK); + revs->pruning.add_remove = file_add_remove; + revs->pruning.change = file_change; ++ revs->pruning.change_fn_data = revs; + revs->sort_order = REV_SORT_IN_GRAPH_ORDER; + revs->dense = 1; + revs->prefix = prefix; +-- +2.15.0 + diff --git a/git.spec b/git.spec index 193d914..a044a96 100644 --- a/git.spec +++ b/git.spec @@ -55,7 +55,7 @@ Name: git Version: 2.9.5 -Release: 2%{?dist} +Release: 3%{?dist} Summary: Fast Version Control System License: GPLv2 Group: Development/Tools @@ -103,6 +103,10 @@ Patch6: 0001-blame-fix-segfault-on-untracked-files.patch # Cherry-picked patch set from 2.10.5 to harden git shell and git cvsserver Patch7: git-2.9.5-git-shell-and-cvsserver-hardening.patch +# https://bugzilla.redhat.com/1510455 (CVE-2017-15298) +# https://github.com/git/git/commit/a937b37e76 +Patch8: 0001-revision-quit-pruning-diff-more-quickly-when-possibl.patch + BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) %if ! %{use_prebuilt_docs} && ! 0%{?_without_docs} @@ -391,6 +395,7 @@ rm -rf "$gpghome" # Cleanup tmp gpg home dir %patch5 -p1 %patch6 -p1 %patch7 -p1 +%patch8 -p1 %if %{use_prebuilt_docs} mkdir -p prebuilt_docs/{html,man} @@ -751,6 +756,10 @@ rm -rf %{buildroot} # No files for you! %changelog +* Tue Nov 07 2017 Todd Zullinger - 2.9.5-3 +- Fix git-clone memory exhaustion (CVE-2017-15298) + Resolves: #1510455, #1510457 + * Tue Sep 26 2017 Todd Zullinger - 2.9.5-2 - Cherry-pick patch set to harden git shell and git cvsserver