Skip to content

Commit

Permalink
Sync with 2.37.4
Browse files Browse the repository at this point in the history
Signed-off-by: Taylor Blau <[email protected]>
  • Loading branch information
ttaylorr committed Oct 7, 2022
2 parents 3dcec76 + 83d5e33 commit f64d4ca
Show file tree
Hide file tree
Showing 73 changed files with 357 additions and 62 deletions.
60 changes: 60 additions & 0 deletions Documentation/RelNotes/2.30.6.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
Git v2.30.6 Release Notes
=========================

This release addresses the security issues CVE-2022-39253 and
CVE-2022-39260.

Fixes since v2.30.5
-------------------

* CVE-2022-39253:
When relying on the `--local` clone optimization, Git dereferences
symbolic links in the source repository before creating hardlinks
(or copies) of the dereferenced link in the destination repository.
This can lead to surprising behavior where arbitrary files are
present in a repository's `$GIT_DIR` when cloning from a malicious
repository.

Git will no longer dereference symbolic links via the `--local`
clone mechanism, and will instead refuse to clone repositories that
have symbolic links present in the `$GIT_DIR/objects` directory.

Additionally, the value of `protocol.file.allow` is changed to be
"user" by default.

* CVE-2022-39260:
An overly-long command string given to `git shell` can result in
overflow in `split_cmdline()`, leading to arbitrary heap writes and
remote code execution when `git shell` is exposed and the directory
`$HOME/git-shell-commands` exists.

`git shell` is taught to refuse interactive commands that are
longer than 4MiB in size. `split_cmdline()` is hardened to reject
inputs larger than 2GiB.

Credit for finding CVE-2022-39253 goes to Cory Snider of Mirantis. The
fix was authored by Taylor Blau, with help from Johannes Schindelin.

Credit for finding CVE-2022-39260 goes to Kevin Backhouse of GitHub.
The fix was authored by Kevin Backhouse, Jeff King, and Taylor Blau.


Jeff King (2):
shell: add basic tests
shell: limit size of interactive commands

Kevin Backhouse (1):
alias.c: reject too-long cmdline strings in split_cmdline()

Taylor Blau (11):
builtin/clone.c: disallow `--local` clones with symlinks
t/lib-submodule-update.sh: allow local submodules
t/t1NNN: allow local submodules
t/2NNNN: allow local submodules
t/t3NNN: allow local submodules
t/t4NNN: allow local submodules
t/t5NNN: allow local submodules
t/t6NNN: allow local submodules
t/t7NNN: allow local submodules
t/t9NNN: allow local submodules
transport: make `protocol.file.allow` be "user" by default
5 changes: 5 additions & 0 deletions Documentation/RelNotes/2.31.5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Git v2.31.5 Release Notes
=========================

This release merges the security fix that appears in v2.30.6; see
the release notes for that version for details.
5 changes: 5 additions & 0 deletions Documentation/RelNotes/2.32.4.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Git v2.32.4 Release Notes
=========================

This release merges the security fix that appears in v2.30.6; see
the release notes for that version for details.
5 changes: 5 additions & 0 deletions Documentation/RelNotes/2.33.5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Git v2.33.5 Release Notes
=========================

This release merges the security fix that appears in v2.30.6; see
the release notes for that version for details.
5 changes: 5 additions & 0 deletions Documentation/RelNotes/2.34.5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Git v2.34.5 Release Notes
=========================

This release merges the security fix that appears in v2.30.6; see
the release notes for that version for details.
5 changes: 5 additions & 0 deletions Documentation/RelNotes/2.35.5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Git v2.35.5 Release Notes
=========================

This release merges the security fix that appears in v2.30.6; see
the release notes for that version for details.
5 changes: 5 additions & 0 deletions Documentation/RelNotes/2.36.3.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Git v2.36.3 Release Notes
=========================

This release merges the security fix that appears in v2.30.6; see
the release notes for that version for details.
36 changes: 35 additions & 1 deletion Documentation/RelNotes/2.37.4.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,45 @@ Git 2.37.4 Release Notes
========================

This primarily is to backport various fixes accumulated on the 'master'
front since 2.37.3.
front since 2.37.3, and also includes the same security fixes as in
v2.30.6.

Fixes since v2.37.3
-------------------

* CVE-2022-39253:
When relying on the `--local` clone optimization, Git dereferences
symbolic links in the source repository before creating hardlinks
(or copies) of the dereferenced link in the destination repository.
This can lead to surprising behavior where arbitrary files are
present in a repository's `$GIT_DIR` when cloning from a malicious
repository.

Git will no longer dereference symbolic links via the `--local`
clone mechanism, and will instead refuse to clone repositories that
have symbolic links present in the `$GIT_DIR/objects` directory.

Additionally, the value of `protocol.file.allow` is changed to be
"user" by default.

Credit for finding CVE-2022-39253 goes to Cory Snider of Mirantis.
The fix was authored by Taylor Blau, with help from Johannes
Schindelin.

* CVE-2022-39260:
An overly-long command string given to `git shell` can result in
overflow in `split_cmdline()`, leading to arbitrary heap writes and
remote code execution when `git shell` is exposed and the directory
`$HOME/git-shell-commands` exists.

`git shell` is taught to refuse interactive commands that are
longer than 4MiB in size. `split_cmdline()` is hardened to reject
inputs larger than 2GiB.

Credit for finding CVE-2022-39260 goes to Kevin Backhouse of
GitHub. The fix was authored by Kevin Backhouse, Jeff King, and
Taylor Blau.

* An earlier optimization discarded a tree-object buffer that is
still in use, which has been corrected.

Expand Down
6 changes: 3 additions & 3 deletions Documentation/config/protocol.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
protocol.allow::
If set, provide a user defined default policy for all protocols which
don't explicitly have a policy (`protocol.<name>.allow`). By default,
if unset, known-safe protocols (http, https, git, ssh, file) have a
if unset, known-safe protocols (http, https, git, ssh) have a
default policy of `always`, known-dangerous protocols (ext) have a
default policy of `never`, and all other protocols have a default
policy of `user`. Supported policies:
default policy of `never`, and all other protocols (including file)
have a default policy of `user`. Supported policies:
+
--

Expand Down
11 changes: 9 additions & 2 deletions alias.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,16 @@ void list_aliases(struct string_list *list)

#define SPLIT_CMDLINE_BAD_ENDING 1
#define SPLIT_CMDLINE_UNCLOSED_QUOTE 2
#define SPLIT_CMDLINE_ARGC_OVERFLOW 3
static const char *split_cmdline_errors[] = {
N_("cmdline ends with \\"),
N_("unclosed quote")
N_("unclosed quote"),
N_("too many arguments"),
};

int split_cmdline(char *cmdline, const char ***argv)
{
int src, dst, count = 0, size = 16;
size_t src, dst, count = 0, size = 16;
char quoted = 0;

ALLOC_ARRAY(*argv, size);
Expand Down Expand Up @@ -96,6 +98,11 @@ int split_cmdline(char *cmdline, const char ***argv)
return -SPLIT_CMDLINE_UNCLOSED_QUOTE;
}

if (count >= INT_MAX) {
FREE_AND_NULL(*argv);
return -SPLIT_CMDLINE_ARGC_OVERFLOW;
}

ALLOC_GROW(*argv, count + 1, size);
(*argv)[count] = NULL;

Expand Down
8 changes: 5 additions & 3 deletions builtin/clone.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,11 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
int src_len, dest_len;
struct dir_iterator *iter;
int iter_status;
unsigned int flags;
struct strbuf realpath = STRBUF_INIT;

mkdir_if_missing(dest->buf, 0777);

flags = DIR_ITERATOR_PEDANTIC | DIR_ITERATOR_FOLLOW_SYMLINKS;
iter = dir_iterator_begin(src->buf, flags);
iter = dir_iterator_begin(src->buf, DIR_ITERATOR_PEDANTIC);

if (!iter)
die_errno(_("failed to start iterator over '%s'"), src->buf);
Expand All @@ -342,6 +340,10 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
strbuf_setlen(dest, dest_len);
strbuf_addstr(dest, iter->relative_path);

if (S_ISLNK(iter->st.st_mode))
die(_("symlink '%s' exists, refusing to clone with --local"),
iter->relative_path);

if (S_ISDIR(iter->st.st_mode)) {
mkdir_if_missing(dest->buf, 0777);
continue;
Expand Down
34 changes: 30 additions & 4 deletions shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ static void cd_to_homedir(void)
die("could not chdir to user's home directory");
}

#define MAX_INTERACTIVE_COMMAND (4*1024*1024)

static void run_shell(void)
{
int done = 0;
Expand All @@ -67,22 +69,46 @@ static void run_shell(void)
run_command_v_opt(help_argv, RUN_SILENT_EXEC_FAILURE);

do {
struct strbuf line = STRBUF_INIT;
const char *prog;
char *full_cmd;
char *rawargs;
size_t len;
char *split_args;
const char **argv;
int code;
int count;

fprintf(stderr, "git> ");
if (git_read_line_interactively(&line) == EOF) {

/*
* Avoid using a strbuf or git_read_line_interactively() here.
* We don't want to allocate arbitrary amounts of memory on
* behalf of a possibly untrusted client, and we're subject to
* OS limits on command length anyway.
*/
fflush(stdout);
rawargs = xmalloc(MAX_INTERACTIVE_COMMAND);
if (!fgets(rawargs, MAX_INTERACTIVE_COMMAND, stdin)) {
fprintf(stderr, "\n");
strbuf_release(&line);
free(rawargs);
break;
}
rawargs = strbuf_detach(&line, NULL);
len = strlen(rawargs);

/*
* If we truncated due to our input buffer size, reject the
* command. That's better than running bogus input, and
* there's a good chance it's just malicious garbage anyway.
*/
if (len >= MAX_INTERACTIVE_COMMAND - 1)
die("invalid command format: input too long");

if (len > 0 && rawargs[len - 1] == '\n') {
if (--len > 0 && rawargs[len - 1] == '\r')
--len;
rawargs[len] = '\0';
}

split_args = xstrdup(rawargs);
count = split_cmdline(split_args, &argv);
if (count < 0) {
Expand Down
1 change: 1 addition & 0 deletions t/lib-submodule-update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ test_git_directory_exists () {
# the submodule repo if it doesn't exist and configures the most problematic
# settings for diff.ignoreSubmodules.
prolog () {
test_config_global protocol.file.allow always &&
(test -d submodule_update_repo || create_lib_submodule_repo) &&
test_config_global diff.ignoreSubmodules all &&
test_config diff.ignoreSubmodules all
Expand Down
3 changes: 2 additions & 1 deletion t/t1091-sparse-checkout-builtin.sh
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,8 @@ test_expect_success 'interaction with submodules' '
(
cd super &&
mkdir modules &&
git submodule add ../repo modules/child &&
git -c protocol.file.allow=always \
submodule add ../repo modules/child &&
git add . &&
git commit -m "add submodule" &&
git sparse-checkout init --cone &&
Expand Down
2 changes: 2 additions & 0 deletions t/t1092-sparse-checkout-compatibility.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,8 @@ test_expect_success 'submodule handling' '
test_all_match git add modules &&
test_all_match git commit -m "add modules directory" &&
test_config_global protocol.file.allow always &&
run_on_all git submodule add "$(pwd)/initial-repo" modules/sub &&
test_all_match git commit -m "add submodule" &&
Expand Down
3 changes: 2 additions & 1 deletion t/t1500-rev-parse.sh
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,8 @@ test_expect_success 'showing the superproject correctly' '
test_commit -C super test_commit &&
test_create_repo sub &&
test_commit -C sub test_commit &&
git -C super submodule add ../sub dir/sub &&
git -c protocol.file.allow=always \
-C super submodule add ../sub dir/sub &&
echo $(pwd)/super >expect &&
git -C super/dir/sub rev-parse --show-superproject-working-tree >out &&
test_cmp expect out &&
Expand Down
3 changes: 3 additions & 0 deletions t/t2080-parallel-checkout-basics.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ TEST_NO_CREATE_REPO=1
# - m/m (file)
#
test_expect_success 'setup repo for checkout with various types of changes' '
test_config_global protocol.file.allow always &&
git init sub &&
(
cd sub &&
Expand Down Expand Up @@ -140,6 +142,7 @@ do
esac

test_expect_success "$mode checkout on clone" '
test_config_global protocol.file.allow always &&
repo=various_${mode}_clone &&
set_checkout_config $workers $threshold &&
test_checkout_workers $expected_workers \
Expand Down
2 changes: 2 additions & 0 deletions t/t2400-worktree-add.sh
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ test_expect_success '"add" should not fail because of another bad worktree' '
'

test_expect_success '"add" with uninitialized submodule, with submodule.recurse unset' '
test_config_global protocol.file.allow always &&
test_create_repo submodule &&
test_commit -C submodule first &&
test_create_repo project &&
Expand All @@ -684,6 +685,7 @@ test_expect_success '"add" with uninitialized submodule, with submodule.recurse
'

test_expect_success '"add" with initialized submodule, with submodule.recurse unset' '
test_config_global protocol.file.allow always &&
git -C project-clone submodule update --init &&
git -C project-clone worktree add ../project-4
'
Expand Down
7 changes: 5 additions & 2 deletions t/t2403-worktree-move.sh
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,8 @@ test_expect_success 'move a repo with uninitialized submodule' '
(
cd withsub &&
test_commit initial &&
git submodule add "$PWD"/.git sub &&
git -c protocol.file.allow=always \
submodule add "$PWD"/.git sub &&
git commit -m withsub &&
git worktree add second HEAD &&
git worktree move second third
Expand All @@ -149,7 +150,7 @@ test_expect_success 'move a repo with uninitialized submodule' '
test_expect_success 'not move a repo with initialized submodule' '
(
cd withsub &&
git -C third submodule update &&
git -c protocol.file.allow=always -C third submodule update &&
test_must_fail git worktree move third forth
)
'
Expand Down Expand Up @@ -228,6 +229,7 @@ test_expect_success 'remove cleans up .git/worktrees when empty' '
'

test_expect_success 'remove a repo with uninitialized submodule' '
test_config_global protocol.file.allow always &&
(
cd withsub &&
git worktree add to-remove HEAD &&
Expand All @@ -236,6 +238,7 @@ test_expect_success 'remove a repo with uninitialized submodule' '
'

test_expect_success 'not remove a repo with initialized submodule' '
test_config_global protocol.file.allow always &&
(
cd withsub &&
git worktree add to-remove HEAD &&
Expand Down
1 change: 1 addition & 0 deletions t/t2405-worktree-submodule.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
base_path=$(pwd -P)

test_expect_success 'setup: create origin repos' '
git config --global protocol.file.allow always &&
git init origin/sub &&
test_commit -C origin/sub file1 &&
git init origin/main &&
Expand Down
1 change: 1 addition & 0 deletions t/t3200-branch.sh
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ test_expect_success 'deleting checked-out branch from repo that is a submodule'
git init repo1 &&
git init repo1/sub &&
test_commit -C repo1/sub x &&
test_config_global protocol.file.allow always &&
git -C repo1 submodule add ./sub &&
git -C repo1 commit -m "adding sub" &&
Expand Down
Loading

0 comments on commit f64d4ca

Please sign in to comment.