!29 fix CVE-2021-21300
From: @liquor1 Reviewed-by: @overweight Signed-off-by: @overweight
This commit is contained in:
commit
bad46e400f
382
backport-CVE-2021-21300.patch
Normal file
382
backport-CVE-2021-21300.patch
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
From 684dd4c2b414bcf648505e74498a608f28de4592 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Matheus Tavares <matheus.bernardino@usp.br>
|
||||||
|
Date: Thu, 10 Dec 2020 10:27:55 -0300
|
||||||
|
Subject: [PATCH] checkout: fix bug that makes checkout follow symlinks in
|
||||||
|
leading path
|
||||||
|
|
||||||
|
Before checking out a file, we have to confirm that all of its leading
|
||||||
|
components are real existing directories. And to reduce the number of
|
||||||
|
lstat() calls in this process, we cache the last leading path known to
|
||||||
|
contain only directories. However, when a path collision occurs (e.g.
|
||||||
|
when checking out case-sensitive files in case-insensitive file
|
||||||
|
systems), a cached path might have its file type changed on disk,
|
||||||
|
leaving the cache on an invalid state. Normally, this doesn't bring
|
||||||
|
any bad consequences as we usually check out files in index order, and
|
||||||
|
therefore, by the time the cached path becomes outdated, we no longer
|
||||||
|
need it anyway (because all files in that directory would have already
|
||||||
|
been written).
|
||||||
|
|
||||||
|
But, there are some users of the checkout machinery that do not always
|
||||||
|
follow the index order. In particular: checkout-index writes the paths
|
||||||
|
in the same order that they appear on the CLI (or stdin); and the
|
||||||
|
delayed checkout feature -- used when a long-running filter process
|
||||||
|
replies with "status=delayed" -- postpones the checkout of some entries,
|
||||||
|
thus modifying the checkout order.
|
||||||
|
|
||||||
|
When we have to check out an out-of-order entry and the lstat() cache is
|
||||||
|
invalid (due to a previous path collision), checkout_entry() may end up
|
||||||
|
using the invalid data and thrusting that the leading components are
|
||||||
|
real directories when, in reality, they are not. In the best case
|
||||||
|
scenario, where the directory was replaced by a regular file, the user
|
||||||
|
will get an error: "fatal: unable to create file 'foo/bar': Not a
|
||||||
|
directory". But if the directory was replaced by a symlink, checkout
|
||||||
|
could actually end up following the symlink and writing the file at a
|
||||||
|
wrong place, even outside the repository. Since delayed checkout is
|
||||||
|
affected by this bug, it could be used by an attacker to write
|
||||||
|
arbitrary files during the clone of a maliciously crafted repository.
|
||||||
|
|
||||||
|
Some candidate solutions considered were to disable the lstat() cache
|
||||||
|
during unordered checkouts or sort the entries before passing them to
|
||||||
|
the checkout machinery. But both ideas include some performance penalty
|
||||||
|
and they don't future-proof the code against new unordered use cases.
|
||||||
|
|
||||||
|
Instead, we now manually reset the lstat cache whenever we successfully
|
||||||
|
remove a directory. Note: We are not even checking whether the directory
|
||||||
|
was the same as the lstat cache points to because we might face a
|
||||||
|
scenario where the paths refer to the same location but differ due to
|
||||||
|
case folding, precomposed UTF-8 issues, or the presence of `..`
|
||||||
|
components in the path. Two regression tests, with case-collisions and
|
||||||
|
utf8-collisions, are also added for both checkout-index and delayed
|
||||||
|
checkout.
|
||||||
|
|
||||||
|
Note: to make the previously mentioned clone attack unfeasible, it would
|
||||||
|
be sufficient to reset the lstat cache only after the remove_subtree()
|
||||||
|
call inside checkout_entry(). This is the place where we would remove a
|
||||||
|
directory whose path collides with the path of another entry that we are
|
||||||
|
currently trying to check out (possibly a symlink). However, in the
|
||||||
|
interest of a thorough fix that does not leave Git open to
|
||||||
|
similar-but-not-identical attack vectors, we decided to intercept
|
||||||
|
all `rmdir()` calls in one fell swoop.
|
||||||
|
|
||||||
|
This addresses CVE-2021-21300.
|
||||||
|
|
||||||
|
Co-authored-by: Johannes Schindelin <johannes.schindelin@gmx.de>
|
||||||
|
Signed-off-by: Matheus Tavares <matheus.bernardino@usp.br>
|
||||||
|
---
|
||||||
|
cache.h | 1 +
|
||||||
|
compat/mingw.c | 2 +
|
||||||
|
git-compat-util.h | 5 +++
|
||||||
|
run-command.c | 9 ++++-
|
||||||
|
symlinks.c | 24 +++++++++++
|
||||||
|
t/t0021-conversion.sh | 71 +++++++++++++++++++++++++++++++++
|
||||||
|
t/t0021/rot13-filter.pl | 21 ++++++++--
|
||||||
|
t/t2006-checkout-index-basic.sh | 40 +++++++++++++++++++
|
||||||
|
unpack-trees.c | 3 ++
|
||||||
|
9 files changed, 172 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/cache.h b/cache.h
|
||||||
|
index 7109765..0a0b32f 100644
|
||||||
|
--- a/cache.h
|
||||||
|
+++ b/cache.h
|
||||||
|
@@ -1657,6 +1657,7 @@ int has_symlink_leading_path(const char *name, int len);
|
||||||
|
int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
|
||||||
|
int check_leading_path(const char *name, int len);
|
||||||
|
int has_dirs_only_path(const char *name, int len, int prefix_len);
|
||||||
|
+void invalidate_lstat_cache(void);
|
||||||
|
void schedule_dir_for_removal(const char *name, int len);
|
||||||
|
void remove_scheduled_dirs(void);
|
||||||
|
|
||||||
|
diff --git a/compat/mingw.c b/compat/mingw.c
|
||||||
|
index a00f331..a435998 100644
|
||||||
|
--- a/compat/mingw.c
|
||||||
|
+++ b/compat/mingw.c
|
||||||
|
@@ -367,6 +367,8 @@ int mingw_rmdir(const char *pathname)
|
||||||
|
ask_yes_no_if_possible("Deletion of directory '%s' failed. "
|
||||||
|
"Should I try again?", pathname))
|
||||||
|
ret = _wrmdir(wpathname);
|
||||||
|
+ if (!ret)
|
||||||
|
+ invalidate_lstat_cache();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/git-compat-util.h b/git-compat-util.h
|
||||||
|
index 104993b..7d3db43 100644
|
||||||
|
--- a/git-compat-util.h
|
||||||
|
+++ b/git-compat-util.h
|
||||||
|
@@ -349,6 +349,11 @@ static inline int noop_core_config(const char *var, const char *value, void *cb)
|
||||||
|
#define platform_core_config noop_core_config
|
||||||
|
#endif
|
||||||
|
|
||||||
|
+int lstat_cache_aware_rmdir(const char *path);
|
||||||
|
+#if !defined(__MINGW32__) && !defined(_MSC_VER)
|
||||||
|
+#define rmdir lstat_cache_aware_rmdir
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
#ifndef has_dos_drive_prefix
|
||||||
|
static inline int git_has_dos_drive_prefix(const char *path)
|
||||||
|
{
|
||||||
|
diff --git a/run-command.c b/run-command.c
|
||||||
|
index ea4d0fb..25fbab2 100644
|
||||||
|
--- a/run-command.c
|
||||||
|
+++ b/run-command.c
|
||||||
|
@@ -990,6 +990,7 @@ int finish_command(struct child_process *cmd)
|
||||||
|
int ret = wait_or_whine(cmd->pid, cmd->argv[0], 0);
|
||||||
|
trace2_child_exit(cmd, ret);
|
||||||
|
child_process_clear(cmd);
|
||||||
|
+ invalidate_lstat_cache();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1291,13 +1292,19 @@ int start_async(struct async *async)
|
||||||
|
int finish_async(struct async *async)
|
||||||
|
{
|
||||||
|
#ifdef NO_PTHREADS
|
||||||
|
- return wait_or_whine(async->pid, "child process", 0);
|
||||||
|
+ int ret = wait_or_whine(async->pid, "child process", 0);
|
||||||
|
+
|
||||||
|
+ invalidate_lstat_cache();
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
#else
|
||||||
|
void *ret = (void *)(intptr_t)(-1);
|
||||||
|
|
||||||
|
if (pthread_join(async->tid, &ret))
|
||||||
|
error("pthread_join failed");
|
||||||
|
+ invalidate_lstat_cache();
|
||||||
|
return (int)(intptr_t)ret;
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/symlinks.c b/symlinks.c
|
||||||
|
index 69d458a..7dbb6b2 100644
|
||||||
|
--- a/symlinks.c
|
||||||
|
+++ b/symlinks.c
|
||||||
|
@@ -267,6 +267,13 @@ int has_dirs_only_path(const char *name, int len, int prefix_len)
|
||||||
|
*/
|
||||||
|
static int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len)
|
||||||
|
{
|
||||||
|
+ /*
|
||||||
|
+ * Note: this function is used by the checkout machinery, which also
|
||||||
|
+ * takes care to properly reset the cache when it performs an operation
|
||||||
|
+ * that would leave the cache outdated. If this function starts caching
|
||||||
|
+ * anything else besides FL_DIR, remember to also invalidate the cache
|
||||||
|
+ * when creating or deleting paths that might be in the cache.
|
||||||
|
+ */
|
||||||
|
return lstat_cache(cache, name, len,
|
||||||
|
FL_DIR|FL_FULLPATH, prefix_len) &
|
||||||
|
FL_DIR;
|
||||||
|
@@ -321,3 +328,20 @@ void remove_scheduled_dirs(void)
|
||||||
|
{
|
||||||
|
do_remove_scheduled_dirs(0);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+void invalidate_lstat_cache(void)
|
||||||
|
+{
|
||||||
|
+ reset_lstat_cache(&default_cache);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+#undef rmdir
|
||||||
|
+int lstat_cache_aware_rmdir(const char *path)
|
||||||
|
+{
|
||||||
|
+ /* Any change in this function must be made also in `mingw_rmdir()` */
|
||||||
|
+ int ret = rmdir(path);
|
||||||
|
+
|
||||||
|
+ if (!ret)
|
||||||
|
+ invalidate_lstat_cache();
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
|
||||||
|
index f6deaf4..cd15ddf 100755
|
||||||
|
--- a/t/t0021-conversion.sh
|
||||||
|
+++ b/t/t0021-conversion.sh
|
||||||
|
@@ -953,4 +953,75 @@ test_expect_success PERL 'invalid file in delayed checkout' '
|
||||||
|
grep "error: external filter .* signaled that .unfiltered. is now available although it has not been delayed earlier" git-stderr.log
|
||||||
|
'
|
||||||
|
|
||||||
|
+for mode in 'case' 'utf-8'
|
||||||
|
+do
|
||||||
|
+ case "$mode" in
|
||||||
|
+ case) dir='A' symlink='a' mode_prereq='CASE_INSENSITIVE_FS' ;;
|
||||||
|
+ utf-8)
|
||||||
|
+ dir=$(printf "\141\314\210") symlink=$(printf "\303\244")
|
||||||
|
+ mode_prereq='UTF8_NFD_TO_NFC' ;;
|
||||||
|
+ esac
|
||||||
|
+
|
||||||
|
+ test_expect_success PERL,SYMLINKS,$mode_prereq \
|
||||||
|
+ "delayed checkout with $mode-collision don't write to the wrong place" '
|
||||||
|
+ test_config_global filter.delay.process \
|
||||||
|
+ "\"$TEST_ROOT/rot13-filter.pl\" --always-delay delayed.log clean smudge delay" &&
|
||||||
|
+ test_config_global filter.delay.required true &&
|
||||||
|
+ git init $mode-collision &&
|
||||||
|
+ (
|
||||||
|
+ cd $mode-collision &&
|
||||||
|
+ mkdir target-dir &&
|
||||||
|
+ empty_oid=$(printf "" | git hash-object -w --stdin) &&
|
||||||
|
+ symlink_oid=$(printf "%s" "$PWD/target-dir" | git hash-object -w --stdin) &&
|
||||||
|
+ attr_oid=$(echo "$dir/z filter=delay" | git hash-object -w --stdin) &&
|
||||||
|
+ cat >objs <<-EOF &&
|
||||||
|
+ 100644 blob $empty_oid $dir/x
|
||||||
|
+ 100644 blob $empty_oid $dir/y
|
||||||
|
+ 100644 blob $empty_oid $dir/z
|
||||||
|
+ 120000 blob $symlink_oid $symlink
|
||||||
|
+ 100644 blob $attr_oid .gitattributes
|
||||||
|
+ EOF
|
||||||
|
+ git update-index --index-info <objs &&
|
||||||
|
+ git commit -m "test commit"
|
||||||
|
+ ) &&
|
||||||
|
+ git clone $mode-collision $mode-collision-cloned &&
|
||||||
|
+ # Make sure z was really delayed
|
||||||
|
+ grep "IN: smudge $dir/z .* \\[DELAYED\\]" $mode-collision-cloned/delayed.log &&
|
||||||
|
+ # Should not create $dir/z at $symlink/z
|
||||||
|
+ test_path_is_missing $mode-collision/target-dir/z
|
||||||
|
+ '
|
||||||
|
+done
|
||||||
|
+
|
||||||
|
+test_expect_success PERL,SYMLINKS,CASE_INSENSITIVE_FS \
|
||||||
|
+"delayed checkout with submodule collision don't write to the wrong place" '
|
||||||
|
+ git init collision-with-submodule &&
|
||||||
|
+ (
|
||||||
|
+ cd collision-with-submodule &&
|
||||||
|
+ git config filter.delay.process "\"$TEST_ROOT/rot13-filter.pl\" --always-delay delayed.log clean smudge delay" &&
|
||||||
|
+ git config filter.delay.required true &&
|
||||||
|
+ # We need Git to treat the submodule "a" and the
|
||||||
|
+ # leading dir "A" as different paths in the index.
|
||||||
|
+ git config --local core.ignoreCase false &&
|
||||||
|
+ empty_oid=$(printf "" | git hash-object -w --stdin) &&
|
||||||
|
+ attr_oid=$(echo "A/B/y filter=delay" | git hash-object -w --stdin) &&
|
||||||
|
+ cat >objs <<-EOF &&
|
||||||
|
+ 100644 blob $empty_oid A/B/x
|
||||||
|
+ 100644 blob $empty_oid A/B/y
|
||||||
|
+ 100644 blob $attr_oid .gitattributes
|
||||||
|
+ EOF
|
||||||
|
+ git update-index --index-info <objs &&
|
||||||
|
+ git init a &&
|
||||||
|
+ mkdir target-dir &&
|
||||||
|
+ symlink_oid=$(printf "%s" "$PWD/target-dir" | git -C a hash-object -w --stdin) &&
|
||||||
|
+ echo "120000 blob $symlink_oid b" >objs &&
|
||||||
|
+ git -C a update-index --index-info <objs &&
|
||||||
|
+ git -C a commit -m sub &&
|
||||||
|
+ git submodule add ./a &&
|
||||||
|
+ git commit -m super &&
|
||||||
|
+ git checkout --recurse-submodules . &&
|
||||||
|
+ grep "IN: smudge A/B/y .* \\[DELAYED\\]" delayed.log &&
|
||||||
|
+ test_path_is_missing target-dir/y
|
||||||
|
+ )
|
||||||
|
+'
|
||||||
|
+
|
||||||
|
test_done
|
||||||
|
diff --git a/t/t0021/rot13-filter.pl b/t/t0021/rot13-filter.pl
|
||||||
|
index cd32a82..b8782f7 100644
|
||||||
|
--- a/t/t0021/rot13-filter.pl
|
||||||
|
+++ b/t/t0021/rot13-filter.pl
|
||||||
|
@@ -2,10 +2,16 @@
|
||||||
|
# Example implementation for the Git filter protocol version 2
|
||||||
|
# See Documentation/gitattributes.txt, section "Filter Protocol"
|
||||||
|
#
|
||||||
|
-# The first argument defines a debug log file that the script write to.
|
||||||
|
-# All remaining arguments define a list of supported protocol
|
||||||
|
-# capabilities ("clean", "smudge", etc).
|
||||||
|
+# Usage: rot13-filter.pl [--always-delay] <log path> <capabilities>
|
||||||
|
#
|
||||||
|
+# Log path defines a debug log file that the script writes to. The
|
||||||
|
+# subsequent arguments define a list of supported protocol capabilities
|
||||||
|
+# ("clean", "smudge", etc).
|
||||||
|
+#
|
||||||
|
+# When --always-delay is given all pathnames with the "can-delay" flag
|
||||||
|
+# that don't appear on the list bellow are delayed with a count of 1
|
||||||
|
+# (see more below).
|
||||||
|
+#
|
||||||
|
# This implementation supports special test cases:
|
||||||
|
# (1) If data with the pathname "clean-write-fail.r" is processed with
|
||||||
|
# a "clean" operation then the write operation will die.
|
||||||
|
@@ -53,6 +59,13 @@ sub gitperllib {
|
||||||
|
use Git::Packet;
|
||||||
|
|
||||||
|
my $MAX_PACKET_CONTENT_SIZE = 65516;
|
||||||
|
+
|
||||||
|
+my $always_delay = 0;
|
||||||
|
+if ( $ARGV[0] eq '--always-delay' ) {
|
||||||
|
+ $always_delay = 1;
|
||||||
|
+ shift @ARGV;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
my $log_file = shift @ARGV;
|
||||||
|
my @capabilities = @ARGV;
|
||||||
|
|
||||||
|
@@ -134,6 +147,8 @@ sub rot13 {
|
||||||
|
if ( $buffer eq "can-delay=1" ) {
|
||||||
|
if ( exists $DELAY{$pathname} and $DELAY{$pathname}{"requested"} == 0 ) {
|
||||||
|
$DELAY{$pathname}{"requested"} = 1;
|
||||||
|
+ } elsif ( !exists $DELAY{$pathname} and $always_delay ) {
|
||||||
|
+ $DELAY{$pathname} = { "requested" => 1, "count" => 1 };
|
||||||
|
}
|
||||||
|
} elsif ($buffer =~ /^(ref|treeish|blob)=/) {
|
||||||
|
print $debug " $buffer";
|
||||||
|
diff --git a/t/t2006-checkout-index-basic.sh b/t/t2006-checkout-index-basic.sh
|
||||||
|
index 8e181db..602d8fe 100755
|
||||||
|
--- a/t/t2006-checkout-index-basic.sh
|
||||||
|
+++ b/t/t2006-checkout-index-basic.sh
|
||||||
|
@@ -32,4 +32,44 @@ test_expect_success 'checkout-index reports errors (stdin)' '
|
||||||
|
test_i18ngrep not.in.the.cache stderr
|
||||||
|
'
|
||||||
|
|
||||||
|
+for mode in 'case' 'utf-8'
|
||||||
|
+do
|
||||||
|
+ case "$mode" in
|
||||||
|
+ case) dir='A' symlink='a' mode_prereq='CASE_INSENSITIVE_FS' ;;
|
||||||
|
+ utf-8)
|
||||||
|
+ dir=$(printf "\141\314\210") symlink=$(printf "\303\244")
|
||||||
|
+ mode_prereq='UTF8_NFD_TO_NFC' ;;
|
||||||
|
+ esac
|
||||||
|
+
|
||||||
|
+ test_expect_success SYMLINKS,$mode_prereq \
|
||||||
|
+ "checkout-index with $mode-collision don't write to the wrong place" '
|
||||||
|
+ git init $mode-collision &&
|
||||||
|
+ (
|
||||||
|
+ cd $mode-collision &&
|
||||||
|
+ mkdir target-dir &&
|
||||||
|
+ empty_obj_hex=$(git hash-object -w --stdin </dev/null) &&
|
||||||
|
+ symlink_hex=$(printf "%s" "$PWD/target-dir" | git hash-object -w --stdin) &&
|
||||||
|
+ cat >objs <<-EOF &&
|
||||||
|
+ 100644 blob ${empty_obj_hex} ${dir}/x
|
||||||
|
+ 100644 blob ${empty_obj_hex} ${dir}/y
|
||||||
|
+ 100644 blob ${empty_obj_hex} ${dir}/z
|
||||||
|
+ 120000 blob ${symlink_hex} ${symlink}
|
||||||
|
+ EOF
|
||||||
|
+ git update-index --index-info <objs &&
|
||||||
|
+ # Note: the order is important here to exercise the
|
||||||
|
+ # case where the file at ${dir} has its type changed by
|
||||||
|
+ # the time Git tries to check out ${dir}/z.
|
||||||
|
+ #
|
||||||
|
+ # Also, we use core.precomposeUnicode=false because we
|
||||||
|
+ # want Git to treat the UTF-8 paths transparently on
|
||||||
|
+ # Mac OS, matching what is in the index.
|
||||||
|
+ #
|
||||||
|
+ git -c core.precomposeUnicode=false checkout-index -f \
|
||||||
|
+ ${dir}/x ${dir}/y ${symlink} ${dir}/z &&
|
||||||
|
+ # Should not create ${dir}/z at ${symlink}/z
|
||||||
|
+ test_path_is_missing target-dir/z
|
||||||
|
+ )
|
||||||
|
+ '
|
||||||
|
+done
|
||||||
|
+
|
||||||
|
test_done
|
||||||
|
diff --git a/unpack-trees.c b/unpack-trees.c
|
||||||
|
index 323280d..2344b5e 100644
|
||||||
|
--- a/unpack-trees.c
|
||||||
|
+++ b/unpack-trees.c
|
||||||
|
@@ -417,6 +417,9 @@ static int check_updates(struct unpack_trees_options *o,
|
||||||
|
|
||||||
|
progress = get_progress(o, index);
|
||||||
|
|
||||||
|
+ /* Start with clean cache to avoid using any possibly outdated info. */
|
||||||
|
+ invalidate_lstat_cache();
|
||||||
|
+
|
||||||
|
git_attr_set_direction(GIT_ATTR_CHECKOUT);
|
||||||
|
|
||||||
|
if (should_update_submodules())
|
||||||
|
--
|
||||||
|
2.23.0
|
||||||
|
|
||||||
10
git.spec
10
git.spec
@ -1,7 +1,7 @@
|
|||||||
%global gitexecdir %{_libexecdir}/git-core
|
%global gitexecdir %{_libexecdir}/git-core
|
||||||
Name: git
|
Name: git
|
||||||
Version: 2.30.0
|
Version: 2.30.0
|
||||||
Release: 1
|
Release: 2
|
||||||
Summary: A popular and widely used Version Control System
|
Summary: A popular and widely used Version Control System
|
||||||
License: GPLv2+ or LGPLv2.1
|
License: GPLv2+ or LGPLv2.1
|
||||||
URL: https://git-scm.com/
|
URL: https://git-scm.com/
|
||||||
@ -12,6 +12,8 @@ Source100: git-gui.desktop
|
|||||||
Source101: git@.service.in
|
Source101: git@.service.in
|
||||||
Source102: git.socket
|
Source102: git.socket
|
||||||
|
|
||||||
|
Patch1: backport-CVE-2021-21300.patch
|
||||||
|
|
||||||
BuildRequires: openssl-devel libcurl-devel expat-devel systemd asciidoc xmlto glib2-devel libsecret-devel pcre-devel desktop-file-utils
|
BuildRequires: openssl-devel libcurl-devel expat-devel systemd asciidoc xmlto glib2-devel libsecret-devel pcre-devel desktop-file-utils
|
||||||
BuildRequires: python3-devel perl-generators perl-interpreter perl-Error perl(Test::More) perl-MailTools perl(Test) gdb
|
BuildRequires: python3-devel perl-generators perl-interpreter perl-Error perl(Test::More) perl-MailTools perl(Test) gdb
|
||||||
Requires: less zlib openssh-clients perl(Term::ReadKey) perl-Git
|
Requires: less zlib openssh-clients perl(Term::ReadKey) perl-Git
|
||||||
@ -259,6 +261,12 @@ make test
|
|||||||
%{_mandir}/man7/git*.7.*
|
%{_mandir}/man7/git*.7.*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Thu Mar 18 2021 lirui <lirui130@huawei.com> - 2.30.0-2
|
||||||
|
- Type:CVE
|
||||||
|
- ID:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:CVE-2021-21300
|
||||||
|
|
||||||
* Wed Jan 27 2021 wangchen <wangchen137@huawei.com> - 2.30.0-1
|
* Wed Jan 27 2021 wangchen <wangchen137@huawei.com> - 2.30.0-1
|
||||||
- Type:enhancement
|
- Type:enhancement
|
||||||
- ID:NA
|
- ID:NA
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user