Skip to content

Commit b1726b1

Browse files
committed
Sync with 2.20.5
* maint-2.20: Git 2.20.5 Git 2.19.6 Git 2.18.5 Git 2.17.6 unpack_trees(): start with a fresh lstat cache run-command: invalidate lstat cache after a command finished checkout: fix bug that makes checkout follow symlinks in leading path
2 parents 9206d27 + 8b1a5f3 commit b1726b1

File tree

13 files changed

+222
-4
lines changed

13 files changed

+222
-4
lines changed

Documentation/RelNotes/2.17.6.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
Git v2.17.6 Release Notes
2+
=========================
3+
4+
This release addresses the security issues CVE-2021-21300.
5+
6+
Fixes since v2.17.5
7+
-------------------
8+
9+
* CVE-2021-21300:
10+
On case-insensitive file systems with support for symbolic links,
11+
if Git is configured globally to apply delay-capable clean/smudge
12+
filters (such as Git LFS), Git could be fooled into running
13+
remote code during a clone.
14+
15+
Credit for finding and fixing this vulnerability goes to Matheus
16+
Tavares, helped by Johannes Schindelin.

Documentation/RelNotes/2.18.5.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Git v2.18.5 Release Notes
2+
=========================
3+
4+
This release merges up the fixes that appear in v2.17.6 to address
5+
the security issue CVE-2021-21300; see the release notes for that
6+
version for details.

Documentation/RelNotes/2.19.6.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Git v2.19.6 Release Notes
2+
=========================
3+
4+
This release merges up the fixes that appear in v2.17.6 and
5+
v2.18.5 to address the security issue CVE-2021-21300; see the
6+
release notes for these versions for details.

Documentation/RelNotes/2.20.5.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Git v2.20.5 Release Notes
2+
=========================
3+
4+
This release merges up the fixes that appear in v2.17.6, v2.18.5
5+
and v2.19.6 to address the security issue CVE-2021-21300; see
6+
the release notes for these versions for details.

cache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1586,6 +1586,7 @@ extern int has_symlink_leading_path(const char *name, int len);
15861586
extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
15871587
extern int check_leading_path(const char *name, int len);
15881588
extern int has_dirs_only_path(const char *name, int len, int prefix_len);
1589+
extern void invalidate_lstat_cache(void);
15891590
extern void schedule_dir_for_removal(const char *name, int len);
15901591
extern void remove_scheduled_dirs(void);
15911592

compat/mingw.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ int mingw_rmdir(const char *pathname)
340340
ask_yes_no_if_possible("Deletion of directory '%s' failed. "
341341
"Should I try again?", pathname))
342342
ret = _wrmdir(wpathname);
343+
if (!ret)
344+
invalidate_lstat_cache();
343345
return ret;
344346
}
345347

git-compat-util.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,11 @@ static inline int noop_core_config(const char *var, const char *value, void *cb)
354354
#define platform_core_config noop_core_config
355355
#endif
356356

357+
int lstat_cache_aware_rmdir(const char *path);
358+
#if !defined(__MINGW32__) && !defined(_MSC_VER)
359+
#define rmdir lstat_cache_aware_rmdir
360+
#endif
361+
357362
#ifndef has_dos_drive_prefix
358363
static inline int git_has_dos_drive_prefix(const char *path)
359364
{

run-command.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -965,6 +965,7 @@ int finish_command(struct child_process *cmd)
965965
{
966966
int ret = wait_or_whine(cmd->pid, cmd->argv[0], 0);
967967
child_process_clear(cmd);
968+
invalidate_lstat_cache();
968969
return ret;
969970
}
970971

@@ -1251,13 +1252,19 @@ int start_async(struct async *async)
12511252
int finish_async(struct async *async)
12521253
{
12531254
#ifdef NO_PTHREADS
1254-
return wait_or_whine(async->pid, "child process", 0);
1255+
int ret = wait_or_whine(async->pid, "child process", 0);
1256+
1257+
invalidate_lstat_cache();
1258+
1259+
return ret;
12551260
#else
12561261
void *ret = (void *)(intptr_t)(-1);
12571262

12581263
if (pthread_join(async->tid, &ret))
12591264
error("pthread_join failed");
1265+
invalidate_lstat_cache();
12601266
return (int)(intptr_t)ret;
1267+
12611268
#endif
12621269
}
12631270

symlinks.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,13 @@ int has_dirs_only_path(const char *name, int len, int prefix_len)
267267
*/
268268
static int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len)
269269
{
270+
/*
271+
* Note: this function is used by the checkout machinery, which also
272+
* takes care to properly reset the cache when it performs an operation
273+
* that would leave the cache outdated. If this function starts caching
274+
* anything else besides FL_DIR, remember to also invalidate the cache
275+
* when creating or deleting paths that might be in the cache.
276+
*/
270277
return lstat_cache(cache, name, len,
271278
FL_DIR|FL_FULLPATH, prefix_len) &
272279
FL_DIR;
@@ -321,3 +328,20 @@ void remove_scheduled_dirs(void)
321328
{
322329
do_remove_scheduled_dirs(0);
323330
}
331+
332+
void invalidate_lstat_cache(void)
333+
{
334+
reset_lstat_cache(&default_cache);
335+
}
336+
337+
#undef rmdir
338+
int lstat_cache_aware_rmdir(const char *path)
339+
{
340+
/* Any change in this function must be made also in `mingw_rmdir()` */
341+
int ret = rmdir(path);
342+
343+
if (!ret)
344+
invalidate_lstat_cache();
345+
346+
return ret;
347+
}

t/t0021-conversion.sh

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,4 +817,85 @@ test_expect_success PERL 'invalid file in delayed checkout' '
817817
grep "error: external filter .* signaled that .unfiltered. is now available although it has not been delayed earlier" git-stderr.log
818818
'
819819

820+
for mode in 'case' 'utf-8'
821+
do
822+
case "$mode" in
823+
case) dir='A' symlink='a' mode_prereq='CASE_INSENSITIVE_FS' ;;
824+
utf-8)
825+
dir=$(printf "\141\314\210") symlink=$(printf "\303\244")
826+
mode_prereq='UTF8_NFD_TO_NFC' ;;
827+
esac
828+
829+
test_expect_success PERL,SYMLINKS,$mode_prereq \
830+
"delayed checkout with $mode-collision don't write to the wrong place" '
831+
test_config_global filter.delay.process \
832+
"\"$TEST_ROOT/rot13-filter.pl\" --always-delay delayed.log clean smudge delay" &&
833+
test_config_global filter.delay.required true &&
834+
835+
git init $mode-collision &&
836+
(
837+
cd $mode-collision &&
838+
mkdir target-dir &&
839+
840+
empty_oid=$(printf "" | git hash-object -w --stdin) &&
841+
symlink_oid=$(printf "%s" "$PWD/target-dir" | git hash-object -w --stdin) &&
842+
attr_oid=$(echo "$dir/z filter=delay" | git hash-object -w --stdin) &&
843+
844+
cat >objs <<-EOF &&
845+
100644 blob $empty_oid $dir/x
846+
100644 blob $empty_oid $dir/y
847+
100644 blob $empty_oid $dir/z
848+
120000 blob $symlink_oid $symlink
849+
100644 blob $attr_oid .gitattributes
850+
EOF
851+
852+
git update-index --index-info <objs &&
853+
git commit -m "test commit"
854+
) &&
855+
856+
git clone $mode-collision $mode-collision-cloned &&
857+
# Make sure z was really delayed
858+
grep "IN: smudge $dir/z .* \\[DELAYED\\]" $mode-collision-cloned/delayed.log &&
859+
860+
# Should not create $dir/z at $symlink/z
861+
test_path_is_missing $mode-collision/target-dir/z
862+
'
863+
done
864+
865+
test_expect_success PERL,SYMLINKS,CASE_INSENSITIVE_FS \
866+
"delayed checkout with submodule collision don't write to the wrong place" '
867+
git init collision-with-submodule &&
868+
(
869+
cd collision-with-submodule &&
870+
git config filter.delay.process "\"$TEST_ROOT/rot13-filter.pl\" --always-delay delayed.log clean smudge delay" &&
871+
git config filter.delay.required true &&
872+
873+
# We need Git to treat the submodule "a" and the
874+
# leading dir "A" as different paths in the index.
875+
git config --local core.ignoreCase false &&
876+
877+
empty_oid=$(printf "" | git hash-object -w --stdin) &&
878+
attr_oid=$(echo "A/B/y filter=delay" | git hash-object -w --stdin) &&
879+
cat >objs <<-EOF &&
880+
100644 blob $empty_oid A/B/x
881+
100644 blob $empty_oid A/B/y
882+
100644 blob $attr_oid .gitattributes
883+
EOF
884+
git update-index --index-info <objs &&
885+
886+
git init a &&
887+
mkdir target-dir &&
888+
symlink_oid=$(printf "%s" "$PWD/target-dir" | git -C a hash-object -w --stdin) &&
889+
echo "120000 blob $symlink_oid b" >objs &&
890+
git -C a update-index --index-info <objs &&
891+
git -C a commit -m sub &&
892+
git submodule add ./a &&
893+
git commit -m super &&
894+
895+
git checkout --recurse-submodules . &&
896+
grep "IN: smudge A/B/y .* \\[DELAYED\\]" delayed.log &&
897+
test_path_is_missing target-dir/y
898+
)
899+
'
900+
820901
test_done

0 commit comments

Comments
 (0)