From a5adaced2e13c135d5d9cc65be9eb95aa3bacedf Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 16 Sep 2015 13:12:52 -0400 Subject: [PATCH 01/12] transport: add a protocol-whitelist environment variable If we are cloning an untrusted remote repository into a sandbox, we may also want to fetch remote submodules in order to get the complete view as intended by the other side. However, that opens us up to attacks where a malicious user gets us to clone something they would not otherwise have access to (this is not necessarily a problem by itself, but we may then act on the cloned contents in a way that exposes them to the attacker). Ideally such a setup would sandbox git entirely away from high-value items, but this is not always practical or easy to set up (e.g., OS network controls may block multiple protocols, and we would want to enable some but not others). We can help this case by providing a way to restrict particular protocols. We use a whitelist in the environment. This is more annoying to set up than a blacklist, but defaults to safety if the set of protocols git supports grows). If no whitelist is specified, we continue to default to allowing all protocols (this is an "unsafe" default, but since the minority of users will want this sandboxing effect, it is the only sensible one). A note on the tests: ideally these would all be in a single test file, but the git-daemon and httpd test infrastructure is an all-or-nothing proposition rather than a test-by-test prerequisite. By putting them all together, we would be unable to test the file-local code on machines without apache. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- Documentation/git.txt | 32 ++++++++++++ connect.c | 5 ++ t/lib-proto-disable.sh | 96 ++++++++++++++++++++++++++++++++++ t/t5810-proto-disable-local.sh | 14 +++++ t/t5811-proto-disable-git.sh | 20 +++++++ t/t5812-proto-disable-http.sh | 20 +++++++ t/t5813-proto-disable-ssh.sh | 20 +++++++ t/t5814-proto-disable-ext.sh | 18 +++++++ transport-helper.c | 2 + transport.c | 21 +++++++- transport.h | 7 +++ 11 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 t/lib-proto-disable.sh create mode 100755 t/t5810-proto-disable-local.sh create mode 100755 t/t5811-proto-disable-git.sh create mode 100755 t/t5812-proto-disable-http.sh create mode 100755 t/t5813-proto-disable-ssh.sh create mode 100755 t/t5814-proto-disable-ext.sh diff --git a/Documentation/git.txt b/Documentation/git.txt index a62ed6f11a..b6a12b32ee 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -1045,6 +1045,38 @@ GIT_ICASE_PATHSPECS:: an operation has touched every ref (e.g., because you are cloning a repository to make a backup). +`GIT_ALLOW_PROTOCOL`:: + If set, provide a colon-separated list of protocols which are + allowed to be used with fetch/push/clone. This is useful to + restrict recursive submodule initialization from an untrusted + repository. Any protocol not mentioned will be disallowed (i.e., + this is a whitelist, not a blacklist). If the variable is not + set at all, all protocols are enabled. The protocol names + currently used by git are: + + - `file`: any local file-based path (including `file://` URLs, + or local paths) + + - `git`: the anonymous git protocol over a direct TCP + connection (or proxy, if configured) + + - `ssh`: git over ssh (including `host:path` syntax, + `git+ssh://`, etc). + + - `rsync`: git over rsync + + - `http`: git over http, both "smart http" and "dumb http". + Note that this does _not_ include `https`; if you want both, + you should specify both as `http:https`. + + - any external helpers are named by their protocol (e.g., use + `hg` to allow the `git-remote-hg` helper) ++ +Note that this controls only git's internal protocol selection. +If libcurl is used (e.g., by the `http` transport), it may +redirect to other protocols. There is not currently any way to +restrict this. + Discussion[[Discussion]] ------------------------ diff --git a/connect.c b/connect.c index 14c924b030..bd4b50ea15 100644 --- a/connect.c +++ b/connect.c @@ -9,6 +9,7 @@ #include "url.h" #include "string-list.h" #include "sha1-array.h" +#include "transport.h" static char *server_capabilities; static const char *parse_feature_value(const char *, const char *, int *); @@ -694,6 +695,8 @@ struct child_process *git_connect(int fd[2], const char *url, else target_host = xstrdup(hostandport); + transport_check_allowed("git"); + /* These underlying connection commands die() if they * cannot connect. */ @@ -727,6 +730,7 @@ struct child_process *git_connect(int fd[2], const char *url, int putty; char *ssh_host = hostandport; const char *port = NULL; + transport_check_allowed("ssh"); get_host_and_port(&ssh_host, &port); if (!port) @@ -768,6 +772,7 @@ struct child_process *git_connect(int fd[2], const char *url, /* remove repo-local variables from the environment */ conn->env = local_repo_env; conn->use_shell = 1; + transport_check_allowed("file"); } argv_array_push(&conn->args, cmd.buf); diff --git a/t/lib-proto-disable.sh b/t/lib-proto-disable.sh new file mode 100644 index 0000000000..b0917d93e6 --- /dev/null +++ b/t/lib-proto-disable.sh @@ -0,0 +1,96 @@ +# Test routines for checking protocol disabling. + +# test cloning a particular protocol +# $1 - description of the protocol +# $2 - machine-readable name of the protocol +# $3 - the URL to try cloning +test_proto () { + desc=$1 + proto=$2 + url=$3 + + test_expect_success "clone $1 (enabled)" ' + rm -rf tmp.git && + ( + GIT_ALLOW_PROTOCOL=$proto && + export GIT_ALLOW_PROTOCOL && + git clone --bare "$url" tmp.git + ) + ' + + test_expect_success "fetch $1 (enabled)" ' + ( + cd tmp.git && + GIT_ALLOW_PROTOCOL=$proto && + export GIT_ALLOW_PROTOCOL && + git fetch + ) + ' + + test_expect_success "push $1 (enabled)" ' + ( + cd tmp.git && + GIT_ALLOW_PROTOCOL=$proto && + export GIT_ALLOW_PROTOCOL && + git push origin HEAD:pushed + ) + ' + + test_expect_success "push $1 (disabled)" ' + ( + cd tmp.git && + GIT_ALLOW_PROTOCOL=none && + export GIT_ALLOW_PROTOCOL && + test_must_fail git push origin HEAD:pushed + ) + ' + + test_expect_success "fetch $1 (disabled)" ' + ( + cd tmp.git && + GIT_ALLOW_PROTOCOL=none && + export GIT_ALLOW_PROTOCOL && + test_must_fail git fetch + ) + ' + + test_expect_success "clone $1 (disabled)" ' + rm -rf tmp.git && + ( + GIT_ALLOW_PROTOCOL=none && + export GIT_ALLOW_PROTOCOL && + test_must_fail git clone --bare "$url" tmp.git + ) + ' +} + +# set up an ssh wrapper that will access $host/$repo in the +# trash directory, and enable it for subsequent tests. +setup_ssh_wrapper () { + test_expect_success 'setup ssh wrapper' ' + write_script ssh-wrapper <<-\EOF && + echo >&2 "ssh: $*" + host=$1; shift + cd "$TRASH_DIRECTORY/$host" && + eval "$*" + EOF + GIT_SSH="$PWD/ssh-wrapper" && + export GIT_SSH && + export TRASH_DIRECTORY + ' +} + +# set up a wrapper that can be used with remote-ext to +# access repositories in the "remote" directory of trash-dir, +# like "ext::fake-remote %S repo.git" +setup_ext_wrapper () { + test_expect_success 'setup ext wrapper' ' + write_script fake-remote <<-\EOF && + echo >&2 "fake-remote: $*" + cd "$TRASH_DIRECTORY/remote" && + eval "$*" + EOF + PATH=$TRASH_DIRECTORY:$PATH && + export TRASH_DIRECTORY + ' +} diff --git a/t/t5810-proto-disable-local.sh b/t/t5810-proto-disable-local.sh new file mode 100755 index 0000000000..563592d8a8 --- /dev/null +++ b/t/t5810-proto-disable-local.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +test_description='test disabling of local paths in clone/fetch' +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-proto-disable.sh" + +test_expect_success 'setup repository to clone' ' + test_commit one +' + +test_proto "file://" file "file://$PWD" +test_proto "path" file . + +test_done diff --git a/t/t5811-proto-disable-git.sh b/t/t5811-proto-disable-git.sh new file mode 100755 index 0000000000..8ac6b2a1d0 --- /dev/null +++ b/t/t5811-proto-disable-git.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +test_description='test disabling of git-over-tcp in clone/fetch' +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-proto-disable.sh" +. "$TEST_DIRECTORY/lib-git-daemon.sh" +start_git_daemon + +test_expect_success 'create git-accessible repo' ' + bare="$GIT_DAEMON_DOCUMENT_ROOT_PATH/repo.git" && + test_commit one && + git --bare init "$bare" && + git push "$bare" HEAD && + >"$bare/git-daemon-export-ok" && + git -C "$bare" config daemon.receivepack true +' + +test_proto "git://" git "$GIT_DAEMON_URL/repo.git" + +test_done diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh new file mode 100755 index 0000000000..dd5001cbac --- /dev/null +++ b/t/t5812-proto-disable-http.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +test_description='test disabling of git-over-http in clone/fetch' +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-proto-disable.sh" +. "$TEST_DIRECTORY/lib-httpd.sh" +start_httpd + +test_expect_success 'create git-accessible repo' ' + bare="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" && + test_commit one && + git --bare init "$bare" && + git push "$bare" HEAD && + git -C "$bare" config http.receivepack true +' + +test_proto "smart http" http "$HTTPD_URL/smart/repo.git" + +stop_httpd +test_done diff --git a/t/t5813-proto-disable-ssh.sh b/t/t5813-proto-disable-ssh.sh new file mode 100755 index 0000000000..ad877d774a --- /dev/null +++ b/t/t5813-proto-disable-ssh.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +test_description='test disabling of git-over-ssh in clone/fetch' +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-proto-disable.sh" + +setup_ssh_wrapper + +test_expect_success 'setup repository to clone' ' + test_commit one && + mkdir remote && + git init --bare remote/repo.git && + git push remote/repo.git HEAD +' + +test_proto "host:path" ssh "remote:repo.git" +test_proto "ssh://" ssh "ssh://remote/$PWD/remote/repo.git" +test_proto "git+ssh://" ssh "git+ssh://remote/$PWD/remote/repo.git" + +test_done diff --git a/t/t5814-proto-disable-ext.sh b/t/t5814-proto-disable-ext.sh new file mode 100755 index 0000000000..9d6f7dfa2c --- /dev/null +++ b/t/t5814-proto-disable-ext.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +test_description='test disabling of remote-helper paths in clone/fetch' +. ./test-lib.sh +. "$TEST_DIRECTORY/lib-proto-disable.sh" + +setup_ext_wrapper + +test_expect_success 'setup repository to clone' ' + test_commit one && + mkdir remote && + git init --bare remote/repo.git && + git push remote/repo.git HEAD +' + +test_proto "remote-helper" ext "ext::fake-remote %S repo.git" + +test_done diff --git a/transport-helper.c b/transport-helper.c index 7dc4a443ae..0b5362c268 100644 --- a/transport-helper.c +++ b/transport-helper.c @@ -1038,6 +1038,8 @@ int transport_helper_init(struct transport *transport, const char *name) struct helper_data *data = xcalloc(1, sizeof(*data)); data->name = name; + transport_check_allowed(name); + if (getenv("GIT_TRANSPORT_HELPER_DEBUG")) debug = 1; diff --git a/transport.c b/transport.c index 88bde1d85e..94fe8658f2 100644 --- a/transport.c +++ b/transport.c @@ -909,6 +909,20 @@ static int external_specification_len(const char *url) return strchr(url, ':') - url; } +void transport_check_allowed(const char *type) +{ + struct string_list allowed = STRING_LIST_INIT_DUP; + const char *v = getenv("GIT_ALLOW_PROTOCOL"); + + if (!v) + return; + + string_list_split(&allowed, v, ':', -1); + if (!unsorted_string_list_has_string(&allowed, type)) + die("transport '%s' not allowed", type); + string_list_clear(&allowed, 0); +} + struct transport *transport_get(struct remote *remote, const char *url) { const char *helper; @@ -940,12 +954,14 @@ struct transport *transport_get(struct remote *remote, const char *url) if (helper) { transport_helper_init(ret, helper); } else if (starts_with(url, "rsync:")) { + transport_check_allowed("rsync"); ret->get_refs_list = get_refs_via_rsync; ret->fetch = fetch_objs_via_rsync; ret->push = rsync_transport_push; ret->smart_options = NULL; } else if (url_is_local_not_ssh(url) && is_file(url) && is_bundle(url, 1)) { struct bundle_transport_data *data = xcalloc(1, sizeof(*data)); + transport_check_allowed("file"); ret->data = data; ret->get_refs_list = get_refs_from_bundle; ret->fetch = fetch_refs_from_bundle; @@ -957,7 +973,10 @@ struct transport *transport_get(struct remote *remote, const char *url) || starts_with(url, "ssh://") || starts_with(url, "git+ssh://") || starts_with(url, "ssh+git://")) { - /* These are builtin smart transports. */ + /* + * These are builtin smart transports; "allowed" transports + * will be checked individually in git_connect. + */ struct git_transport_data *data = xcalloc(1, sizeof(*data)); ret->data = data; ret->set_option = NULL; diff --git a/transport.h b/transport.h index 3e0091eaab..f7df6ec1d2 100644 --- a/transport.h +++ b/transport.h @@ -132,6 +132,13 @@ struct transport { /* Returns a transport suitable for the url */ struct transport *transport_get(struct remote *, const char *); +/* + * Check whether a transport is allowed by the environment, + * and die otherwise. type should generally be the URL scheme, + * as described in Documentation/git.txt + */ +void transport_check_allowed(const char *type); + /* Transport options which apply to git:// and scp-style URLs */ /* The program to use on the remote side to send a pack */ From 33cfccbbf35a56e190b79bdec5c85457c952a021 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Wed, 16 Sep 2015 13:13:12 -0400 Subject: [PATCH 02/12] submodule: allow only certain protocols for submodule fetches Some protocols (like git-remote-ext) can execute arbitrary code found in the URL. The URLs that submodules use may come from arbitrary sources (e.g., .gitmodules files in a remote repository). Let's restrict submodules to fetching from a known-good subset of protocols. Note that we apply this restriction to all submodule commands, whether the URL comes from .gitmodules or not. This is more restrictive than we need to be; for example, in the tests we run: git submodule add ext::... which should be trusted, as the URL comes directly from the command line provided by the user. But doing it this way is simpler, and makes it much less likely that we would miss a case. And since such protocols should be an exception (especially because nobody who clones from them will be able to update the submodules!), it's not likely to inconvenience anyone in practice. Reported-by: Blake Burkhart Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- git-submodule.sh | 9 ++++++++ t/t5815-submodule-protos.sh | 43 +++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100755 t/t5815-submodule-protos.sh diff --git a/git-submodule.sh b/git-submodule.sh index 36797c3c00..78c2740fdb 100755 --- a/git-submodule.sh +++ b/git-submodule.sh @@ -22,6 +22,15 @@ require_work_tree wt_prefix=$(git rev-parse --show-prefix) cd_to_toplevel +# Restrict ourselves to a vanilla subset of protocols; the URLs +# we get are under control of a remote repository, and we do not +# want them kicking off arbitrary git-remote-* programs. +# +# If the user has already specified a set of allowed protocols, +# we assume they know what they're doing and use that instead. +: ${GIT_ALLOW_PROTOCOL=file:git:http:https:ssh} +export GIT_ALLOW_PROTOCOL + command= branch= force= diff --git a/t/t5815-submodule-protos.sh b/t/t5815-submodule-protos.sh new file mode 100755 index 0000000000..06f55a1b8a --- /dev/null +++ b/t/t5815-submodule-protos.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +test_description='test protocol whitelisting with submodules' +. ./test-lib.sh +. "$TEST_DIRECTORY"/lib-proto-disable.sh + +setup_ext_wrapper +setup_ssh_wrapper + +test_expect_success 'setup repository with submodules' ' + mkdir remote && + git init remote/repo.git && + (cd remote/repo.git && test_commit one) && + # submodule-add should probably trust what we feed it on the cmdline, + # but its implementation is overly conservative. + GIT_ALLOW_PROTOCOL=ssh git submodule add remote:repo.git ssh-module && + GIT_ALLOW_PROTOCOL=ext git submodule add "ext::fake-remote %S repo.git" ext-module && + git commit -m "add submodules" +' + +test_expect_success 'clone with recurse-submodules fails' ' + test_must_fail git clone --recurse-submodules . dst +' + +test_expect_success 'setup individual updates' ' + rm -rf dst && + git clone . dst && + git -C dst submodule init +' + +test_expect_success 'update of ssh allowed' ' + git -C dst submodule update ssh-module +' + +test_expect_success 'update of ext not allowed' ' + test_must_fail git -C dst submodule update ext-module +' + +test_expect_success 'user can override whitelist' ' + GIT_ALLOW_PROTOCOL=ext git -C dst submodule update ext-module +' + +test_done From 5088d3b38775f8ac12d7f77636775b16059b67ef Mon Sep 17 00:00:00 2001 From: Jeff King Date: Tue, 22 Sep 2015 18:03:49 -0400 Subject: [PATCH 03/12] transport: refactor protocol whitelist code The current callers only want to die when their transport is prohibited. But future callers want to query the mechanism without dying. Let's break out a few query functions, and also save the results in a static list so we don't have to re-parse for each query. Based-on-a-patch-by: Blake Burkhart Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- transport.c | 40 +++++++++++++++++++++++++++++++--------- transport.h | 15 +++++++++++++-- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/transport.c b/transport.c index 94fe8658f2..647d2c2afa 100644 --- a/transport.c +++ b/transport.c @@ -909,18 +909,40 @@ static int external_specification_len(const char *url) return strchr(url, ':') - url; } +static const struct string_list *protocol_whitelist(void) +{ + static int enabled = -1; + static struct string_list allowed = STRING_LIST_INIT_DUP; + + if (enabled < 0) { + const char *v = getenv("GIT_ALLOW_PROTOCOL"); + if (v) { + string_list_split(&allowed, v, ':', -1); + string_list_sort(&allowed); + enabled = 1; + } else { + enabled = 0; + } + } + + return enabled ? &allowed : NULL; +} + +int is_transport_allowed(const char *type) +{ + const struct string_list *allowed = protocol_whitelist(); + return !allowed || string_list_has_string(allowed, type); +} + void transport_check_allowed(const char *type) { - struct string_list allowed = STRING_LIST_INIT_DUP; - const char *v = getenv("GIT_ALLOW_PROTOCOL"); - - if (!v) - return; - - string_list_split(&allowed, v, ':', -1); - if (!unsorted_string_list_has_string(&allowed, type)) + if (!is_transport_allowed(type)) die("transport '%s' not allowed", type); - string_list_clear(&allowed, 0); +} + +int transport_restrict_protocols(void) +{ + return !!protocol_whitelist(); } struct transport *transport_get(struct remote *remote, const char *url) diff --git a/transport.h b/transport.h index f7df6ec1d2..ed84da2aa4 100644 --- a/transport.h +++ b/transport.h @@ -132,13 +132,24 @@ struct transport { /* Returns a transport suitable for the url */ struct transport *transport_get(struct remote *, const char *); +/* + * Check whether a transport is allowed by the environment. Type should + * generally be the URL scheme, as described in Documentation/git.txt + */ +int is_transport_allowed(const char *type); + /* * Check whether a transport is allowed by the environment, - * and die otherwise. type should generally be the URL scheme, - * as described in Documentation/git.txt + * and die otherwise. */ void transport_check_allowed(const char *type); +/* + * Returns true if the user has attempted to turn on protocol + * restrictions at all. + */ +int transport_restrict_protocols(void); + /* Transport options which apply to git:// and scp-style URLs */ /* The program to use on the remote side to send a pack */ From f4113cac0c88b4f36ee6f3abf3218034440a68e3 Mon Sep 17 00:00:00 2001 From: Blake Burkhart Date: Tue, 22 Sep 2015 18:06:04 -0400 Subject: [PATCH 04/12] http: limit redirection to protocol-whitelist Previously, libcurl would follow redirection to any protocol it was compiled for support with. This is desirable to allow redirection from HTTP to HTTPS. However, it would even successfully allow redirection from HTTP to SFTP, a protocol that git does not otherwise support at all. Furthermore git's new protocol-whitelisting could be bypassed by following a redirect within the remote helper, as it was only enforced at transport selection time. This patch limits redirects within libcurl to HTTP, HTTPS, FTP and FTPS. If there is a protocol-whitelist present, this list is limited to those also allowed by the whitelist. As redirection happens from within libcurl, it is impossible for an HTTP redirect to a protocol implemented within another remote helper. When the curl version git was compiled with is too old to support restrictions on protocol redirection, we warn the user if GIT_ALLOW_PROTOCOL restrictions were requested. This is a little inaccurate, as even without that variable in the environment, we would still restrict SFTP, etc, and we do not warn in that case. But anything else means we would literally warn every time git accesses an http remote. This commit includes a test, but it is not as robust as we would hope. It redirects an http request to ftp, and checks that curl complained about the protocol, which means that we are relying on curl's specific error message to know what happened. Ideally we would redirect to a working ftp server and confirm that we can clone without protocol restrictions, and not with them. But we do not have a portable way of providing an ftp server, nor any other protocol that curl supports (https is the closest, but we would have to deal with certificates). [jk: added test and version warning] Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- Documentation/git.txt | 5 ----- http.c | 17 +++++++++++++++++ t/lib-httpd/apache.conf | 1 + t/t5812-proto-disable-http.sh | 9 +++++++++ 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Documentation/git.txt b/Documentation/git.txt index b6a12b32ee..41a09cac7a 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -1071,11 +1071,6 @@ GIT_ICASE_PATHSPECS:: - any external helpers are named by their protocol (e.g., use `hg` to allow the `git-remote-hg` helper) -+ -Note that this controls only git's internal protocol selection. -If libcurl is used (e.g., by the `http` transport), it may -redirect to other protocols. There is not currently any way to -restrict this. Discussion[[Discussion]] diff --git a/http.c b/http.c index 6798620065..5a57bccea9 100644 --- a/http.c +++ b/http.c @@ -8,6 +8,7 @@ #include "credential.h" #include "version.h" #include "pkt-line.h" +#include "transport.h" int active_requests; int http_is_verbose; @@ -303,6 +304,7 @@ static void set_curl_keepalive(CURL *c) static CURL *get_curl_handle(void) { CURL *result = curl_easy_init(); + long allowed_protocols = 0; if (!result) die("curl_easy_init failed"); @@ -355,6 +357,21 @@ static CURL *get_curl_handle(void) #elif LIBCURL_VERSION_NUM >= 0x071101 curl_easy_setopt(result, CURLOPT_POST301, 1); #endif +#if LIBCURL_VERSION_NUM >= 0x071304 + if (is_transport_allowed("http")) + allowed_protocols |= CURLPROTO_HTTP; + if (is_transport_allowed("https")) + allowed_protocols |= CURLPROTO_HTTPS; + if (is_transport_allowed("ftp")) + allowed_protocols |= CURLPROTO_FTP; + if (is_transport_allowed("ftps")) + allowed_protocols |= CURLPROTO_FTPS; + curl_easy_setopt(result, CURLOPT_REDIR_PROTOCOLS, allowed_protocols); +#else + if (transport_restrict_protocols()) + warning("protocol restrictions not applied to curl redirects because\n" + "your curl version is too old (>= 7.19.4)"); +#endif if (getenv("GIT_CURL_VERBOSE")) curl_easy_setopt(result, CURLOPT_VERBOSE, 1); diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 0b81a0047b..68ef8adb8e 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -119,6 +119,7 @@ RewriteRule ^/smart-redir-perm/(.*)$ /smart/$1 [R=301] RewriteRule ^/smart-redir-temp/(.*)$ /smart/$1 [R=302] RewriteRule ^/smart-redir-auth/(.*)$ /auth/smart/$1 [R=301] RewriteRule ^/smart-redir-limited/(.*)/info/refs$ /smart/$1/info/refs [R=301] +RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302] LoadModule ssl_module modules/mod_ssl.so diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh index dd5001cbac..6a4f81662d 100755 --- a/t/t5812-proto-disable-http.sh +++ b/t/t5812-proto-disable-http.sh @@ -16,5 +16,14 @@ test_expect_success 'create git-accessible repo' ' test_proto "smart http" http "$HTTPD_URL/smart/repo.git" +test_expect_success 'curl redirects respect whitelist' ' + test_must_fail env GIT_ALLOW_PROTOCOL=http:https \ + git clone "$HTTPD_URL/ftp-redir/repo.git" 2>stderr && + { + test_i18ngrep "ftp.*disabled" stderr || + test_i18ngrep "your curl version is too old" + } +' + stop_httpd test_done From b258116462399b318c86165c61a5c7123043cfd4 Mon Sep 17 00:00:00 2001 From: Blake Burkhart Date: Tue, 22 Sep 2015 18:06:20 -0400 Subject: [PATCH 05/12] http: limit redirection depth By default, libcurl will follow circular http redirects forever. Let's put a cap on this so that somebody who can trigger an automated fetch of an arbitrary repository (e.g., for CI) cannot convince git to loop infinitely. The value chosen is 20, which is the same default that Firefox uses. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- http.c | 1 + t/lib-httpd/apache.conf | 3 +++ t/t5812-proto-disable-http.sh | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/http.c b/http.c index 5a57bccea9..00e3fc80e8 100644 --- a/http.c +++ b/http.c @@ -352,6 +352,7 @@ static CURL *get_curl_handle(void) } curl_easy_setopt(result, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(result, CURLOPT_MAXREDIRS, 20); #if LIBCURL_VERSION_NUM >= 0x071301 curl_easy_setopt(result, CURLOPT_POSTREDIR, CURL_REDIR_POST_ALL); #elif LIBCURL_VERSION_NUM >= 0x071101 diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf index 68ef8adb8e..7d15e6d44c 100644 --- a/t/lib-httpd/apache.conf +++ b/t/lib-httpd/apache.conf @@ -121,6 +121,9 @@ RewriteRule ^/smart-redir-auth/(.*)$ /auth/smart/$1 [R=301] RewriteRule ^/smart-redir-limited/(.*)/info/refs$ /smart/$1/info/refs [R=301] RewriteRule ^/ftp-redir/(.*)$ ftp://localhost:1000/$1 [R=302] +RewriteRule ^/loop-redir/x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-(.*) /$1 [R=302] +RewriteRule ^/loop-redir/(.*)$ /loop-redir/x-$1 [R=302] + LoadModule ssl_module modules/mod_ssl.so diff --git a/t/t5812-proto-disable-http.sh b/t/t5812-proto-disable-http.sh index 6a4f81662d..0d105d5417 100755 --- a/t/t5812-proto-disable-http.sh +++ b/t/t5812-proto-disable-http.sh @@ -25,5 +25,9 @@ test_expect_success 'curl redirects respect whitelist' ' } ' +test_expect_success 'curl limits redirects' ' + test_must_fail git clone "$HTTPD_URL/loop-redir/smart/repo.git" +' + stop_httpd test_done From 3efb988098858bf6b974b1e673a190f9d2965d1d Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 24 Sep 2015 19:12:23 -0400 Subject: [PATCH 06/12] react to errors in xdi_diff When we call into xdiff to perform a diff, we generally lose the return code completely. Typically by ignoring the return of our xdi_diff wrapper, but sometimes we even propagate that return value up and then ignore it later. This can lead to us silently producing incorrect diffs (e.g., "git log" might produce no output at all, not even a diff header, for a content-level diff). In practice this does not happen very often, because the typical reason for xdiff to report failure is that it malloc() failed (it uses straight malloc, and not our xmalloc wrapper). But it could also happen when xdiff triggers one our callbacks, which returns an error (e.g., outf() in builtin/rerere.c tries to report a write failure in this way). And the next patch also plans to add more failure modes. Let's notice an error return from xdiff and react appropriately. In most of the diff.c code, we can simply die(), which matches the surrounding code (e.g., that is what we do if we fail to load a file for diffing in the first place). This is not that elegant, but we are probably better off dying to let the user know there was a problem, rather than simply generating bogus output. We could also just die() directly in xdi_diff, but the callers typically have a bit more context, and can provide a better message (and if we do later decide to pass errors up, we're one step closer to doing so). There is one interesting case, which is in diff_grep(). Here if we cannot generate the diff, there is nothing to match, and we silently return "no hits". This is actually what the existing code does already, but we make it a little more explicit. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/blame.c | 9 +++++++-- builtin/merge-tree.c | 3 ++- builtin/rerere.c | 10 ++++++---- combine-diff.c | 6 ++++-- diff.c | 26 ++++++++++++++++---------- diffcore-pickaxe.c | 4 ++-- line-log.c | 7 ++++--- 7 files changed, 41 insertions(+), 24 deletions(-) diff --git a/builtin/blame.c b/builtin/blame.c index 2b1f9dd6cd..66b4fbf466 100644 --- a/builtin/blame.c +++ b/builtin/blame.c @@ -972,7 +972,10 @@ static void pass_blame_to_parent(struct scoreboard *sb, fill_origin_blob(&sb->revs->diffopt, target, &file_o); num_get_patch++; - diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d); + if (diff_hunks(&file_p, &file_o, 0, blame_chunk_cb, &d)) + die("unable to generate diff (%s -> %s)", + sha1_to_hex(parent->commit->object.sha1), + sha1_to_hex(target->commit->object.sha1)); /* The rest are the same as the parent */ blame_chunk(&d.dstq, &d.srcq, INT_MAX, d.offset, INT_MAX, parent); *d.dstq = NULL; @@ -1118,7 +1121,9 @@ static void find_copy_in_blob(struct scoreboard *sb, * file_p partially may match that image. */ memset(split, 0, sizeof(struct blame_entry [3])); - diff_hunks(file_p, &file_o, 1, handle_split_cb, &d); + if (diff_hunks(file_p, &file_o, 1, handle_split_cb, &d)) + die("unable to generate diff (%s)", + sha1_to_hex(parent->commit->object.sha1)); /* remainder, if any, all match the preimage */ handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split); } diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c index f9ab48597e..2a4aafec6a 100644 --- a/builtin/merge-tree.c +++ b/builtin/merge-tree.c @@ -118,7 +118,8 @@ static void show_diff(struct merge_list *entry) if (!dst.ptr) size = 0; dst.size = size; - xdi_diff(&src, &dst, &xpp, &xecfg, &ecb); + if (xdi_diff(&src, &dst, &xpp, &xecfg, &ecb)) + die("unable to generate diff"); free(src.ptr); free(dst.ptr); } diff --git a/builtin/rerere.c b/builtin/rerere.c index 98eb8c5404..aab8f3b1f0 100644 --- a/builtin/rerere.c +++ b/builtin/rerere.c @@ -29,9 +29,10 @@ static int diff_two(const char *file1, const char *label1, xdemitconf_t xecfg; xdemitcb_t ecb; mmfile_t minus, plus; + int ret; if (read_mmfile(&minus, file1) || read_mmfile(&plus, file2)) - return 1; + return -1; printf("--- a/%s\n+++ b/%s\n", label1, label2); fflush(stdout); @@ -40,11 +41,11 @@ static int diff_two(const char *file1, const char *label1, memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 3; ecb.outf = outf; - xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb); + ret = xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb); free(minus.ptr); free(plus.ptr); - return 0; + return ret; } int cmd_rerere(int argc, const char **argv, const char *prefix) @@ -104,7 +105,8 @@ int cmd_rerere(int argc, const char **argv, const char *prefix) for (i = 0; i < merge_rr.nr; i++) { const char *path = merge_rr.items[i].string; const char *name = (const char *)merge_rr.items[i].util; - diff_two(rerere_path(name, "preimage"), path, path, path); + if (diff_two(rerere_path(name, "preimage"), path, path, path)) + die("unable to generate diff for %s", name); } else usage_with_options(rerere_usage, options); diff --git a/combine-diff.c b/combine-diff.c index 91edce58e1..284bec6ad5 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -419,8 +419,10 @@ static void combine_diff(const unsigned char *parent, unsigned int mode, state.num_parent = num_parent; state.n = n; - xdi_diff_outf(&parent_file, result_file, consume_line, &state, - &xpp, &xecfg); + if (xdi_diff_outf(&parent_file, result_file, consume_line, &state, + &xpp, &xecfg)) + die("unable to generate combined diff for %s", + sha1_to_hex(parent)); free(parent_file.ptr); /* Assign line numbers for this parent. diff --git a/diff.c b/diff.c index 7500c55095..6bbf28bff2 100644 --- a/diff.c +++ b/diff.c @@ -1002,8 +1002,9 @@ static void diff_words_show(struct diff_words_data *diff_words) xpp.flags = 0; /* as only the hunk header will be parsed, we need a 0-context */ xecfg.ctxlen = 0; - xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words, - &xpp, &xecfg); + if (xdi_diff_outf(&minus, &plus, fn_out_diff_words_aux, diff_words, + &xpp, &xecfg)) + die("unable to generate word diff"); free(minus.ptr); free(plus.ptr); if (diff_words->current_plus != diff_words->plus.text.ptr + @@ -2400,8 +2401,9 @@ static void builtin_diff(const char *name_a, xecfg.ctxlen = strtoul(v, NULL, 10); if (o->word_diff) init_diff_words_data(&ecbdata, o, one, two); - xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata, - &xpp, &xecfg); + if (xdi_diff_outf(&mf1, &mf2, fn_out_consume, &ecbdata, + &xpp, &xecfg)) + die("unable to generate diff for %s", one->path); if (o->word_diff) free_diff_words_data(&ecbdata); if (textconv_one) @@ -2478,8 +2480,9 @@ static void builtin_diffstat(const char *name_a, const char *name_b, xpp.flags = o->xdl_opts; xecfg.ctxlen = o->context; xecfg.interhunkctxlen = o->interhunkcontext; - xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat, - &xpp, &xecfg); + if (xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat, + &xpp, &xecfg)) + die("unable to generate diffstat for %s", one->path); } diff_free_filespec_data(one); @@ -2525,8 +2528,9 @@ static void builtin_checkdiff(const char *name_a, const char *name_b, memset(&xecfg, 0, sizeof(xecfg)); xecfg.ctxlen = 1; /* at least one context line */ xpp.flags = 0; - xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data, - &xpp, &xecfg); + if (xdi_diff_outf(&mf1, &mf2, checkdiff_consume, &data, + &xpp, &xecfg)) + die("unable to generate checkdiff for %s", one->path); if (data.ws_rule & WS_BLANK_AT_EOF) { struct emit_callback ecbdata; @@ -4425,8 +4429,10 @@ static int diff_get_patch_id(struct diff_options *options, unsigned char *sha1) xpp.flags = 0; xecfg.ctxlen = 3; xecfg.flags = 0; - xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data, - &xpp, &xecfg); + if (xdi_diff_outf(&mf1, &mf2, patch_id_consume, &data, + &xpp, &xecfg)) + return error("unable to generate patch-id diff for %s", + p->one->path); } git_SHA1_Final(sha1, &ctx); diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c index 185f86b284..7715c13ec4 100644 --- a/diffcore-pickaxe.c +++ b/diffcore-pickaxe.c @@ -62,8 +62,8 @@ static int diff_grep(mmfile_t *one, mmfile_t *two, ecbdata.hit = 0; xecfg.ctxlen = o->context; xecfg.interhunkctxlen = o->interhunkcontext; - xdi_diff_outf(one, two, diffgrep_consume, &ecbdata, - &xpp, &xecfg); + if (xdi_diff_outf(one, two, diffgrep_consume, &ecbdata, &xpp, &xecfg)) + return 0; return ecbdata.hit; } diff --git a/line-log.c b/line-log.c index 1a6bc5921b..d4e29a574f 100644 --- a/line-log.c +++ b/line-log.c @@ -325,7 +325,7 @@ static int collect_diff_cb(long start_a, long count_a, return 0; } -static void collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges *out) +static int collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges *out) { struct collect_diff_cbdata cbdata = {NULL}; xpparam_t xpp; @@ -340,7 +340,7 @@ static void collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges xecfg.hunk_func = collect_diff_cb; memset(&ecb, 0, sizeof(ecb)); ecb.priv = &cbdata; - xdi_diff(parent, target, &xpp, &xecfg, &ecb); + return xdi_diff(parent, target, &xpp, &xecfg, &ecb); } /* @@ -1030,7 +1030,8 @@ static int process_diff_filepair(struct rev_info *rev, } diff_ranges_init(&diff); - collect_diff(&file_parent, &file_target, &diff); + if (collect_diff(&file_parent, &file_target, &diff)) + die("unable to generate diff for %s", pair->one->path); /* NEEDSWORK should apply some heuristics to prevent mismatches */ free(rg->path); From dcd1742e56ebb944c4ff62346da4548e1e3be675 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 24 Sep 2015 19:12:45 -0400 Subject: [PATCH 07/12] xdiff: reject files larger than ~1GB The xdiff code is not prepared to handle extremely large files. It uses "int" in many places, which can overflow if we have a very large number of lines or even bytes in our input files. This can cause us to produce incorrect diffs, with no indication that the output is wrong. Or worse, we may even underallocate a buffer whose size is the result of an overflowing addition. We're much better off to tell the user that we cannot diff or merge such a large file. This patch covers both cases, but in slightly different ways: 1. For merging, we notice the large file and cleanly fall back to a binary merge (which is effectively "we cannot merge this"). 2. For diffing, we make the binary/text distinction much earlier, and in many different places. For this case, we'll use the xdi_diff as our choke point, and reject any diff there before it hits the xdiff code. This means in most cases we'll die() immediately after. That's not ideal, but in practice we shouldn't generally hit this code path unless the user is trying to do something tricky. We already consider files larger than core.bigfilethreshold to be binary, so this code would only kick in when that is circumvented (either by bumping that value, or by using a .gitattribute to mark a file as diffable). In other words, we can avoid being "nice" here, because there is already nice code that tries to do the right thing. We are adding the suspenders to the nice code's belt, so notice when it has been worked around (both to protect the user from malicious inputs, and because it is better to die() than generate bogus output). The maximum size was chosen after experimenting with feeding large files to the xdiff code. It's just under a gigabyte, which leaves room for two obvious cases: - a diff3 merge conflict result on files of maximum size X could be 3*X plus the size of the markers, which would still be only about 3G, which fits in a 32-bit int. - some of the diff code allocates arrays of one int per record. Even if each file consists only of blank lines, then a file smaller than 1G will have fewer than 1G records, and therefore the int array will fit in 4G. Since the limit is arbitrary anyway, I chose to go under a gigabyte, to leave a safety margin (e.g., we would not want to overflow by allocating "(records + 1) * sizeof(int)" or similar. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- ll-merge.c | 5 ++++- xdiff-interface.c | 3 +++ xdiff-interface.h | 7 +++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/ll-merge.c b/ll-merge.c index 8ea03e536a..4e789f5330 100644 --- a/ll-merge.c +++ b/ll-merge.c @@ -88,7 +88,10 @@ static int ll_xdl_merge(const struct ll_merge_driver *drv_unused, xmparam_t xmp; assert(opts); - if (buffer_is_binary(orig->ptr, orig->size) || + if (orig->size > MAX_XDIFF_SIZE || + src1->size > MAX_XDIFF_SIZE || + src2->size > MAX_XDIFF_SIZE || + buffer_is_binary(orig->ptr, orig->size) || buffer_is_binary(src1->ptr, src1->size) || buffer_is_binary(src2->ptr, src2->size)) { return ll_binary_merge(drv_unused, result, diff --git a/xdiff-interface.c b/xdiff-interface.c index ecfa05f616..cb67c1c42b 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -131,6 +131,9 @@ int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t co mmfile_t a = *mf1; mmfile_t b = *mf2; + if (mf1->size > MAX_XDIFF_SIZE || mf2->size > MAX_XDIFF_SIZE) + return -1; + trim_common_tail(&a, &b, xecfg->ctxlen); return xdl_diff(&a, &b, xpp, xecfg, xecb); diff --git a/xdiff-interface.h b/xdiff-interface.h index eff7762ee1..fbb5a1c394 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -3,6 +3,13 @@ #include "xdiff/xdiff.h" +/* + * xdiff isn't equipped to handle content over a gigabyte; + * we make the cutoff 1GB - 1MB to give some breathing + * room for constant-sized additions (e.g., merge markers) + */ +#define MAX_XDIFF_SIZE (1024UL * 1024 * 1023) + typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long); int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb); From 83c4d380171a2ecd24dd2e04072692ec54a7aaa5 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Fri, 25 Sep 2015 17:58:09 -0400 Subject: [PATCH 08/12] merge-file: enforce MAX_XDIFF_SIZE on incoming files The previous commit enforces MAX_XDIFF_SIZE at the interfaces to xdiff: xdi_diff (which calls xdl_diff) and ll_xdl_merge (which calls xdl_merge). But we have another direct call to xdl_merge in merge-file.c. If it were written today, this probably would just use the ll_merge machinery. But it predates that code, and uses slightly different options to xdl_merge (e.g., ZEALOUS_ALNUM). We could try to abstract out an xdi_merge to match the existing xdi_diff, but even that is difficult. Rather than simply report error, we try to treat large files as binary, and that distinction would happen outside of xdi_merge. The simplest fix is to just replicate the MAX_XDIFF_SIZE check in merge-file.c. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- builtin/merge-file.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/builtin/merge-file.c b/builtin/merge-file.c index 232b76857c..04ae36a452 100644 --- a/builtin/merge-file.c +++ b/builtin/merge-file.c @@ -75,7 +75,8 @@ int cmd_merge_file(int argc, const char **argv, const char *prefix) names[i] = argv[i]; if (read_mmfile(mmfs + i, fname)) return -1; - if (buffer_is_binary(mmfs[i].ptr, mmfs[i].size)) + if (mmfs[i].size > MAX_XDIFF_SIZE || + buffer_is_binary(mmfs[i].ptr, mmfs[i].size)) return error("Cannot merge binary files: %s", argv[i]); } From 18b58f707fdb3ad7d3d4931bd40693834c9ec8a0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 28 Sep 2015 15:00:37 -0700 Subject: [PATCH 09/12] Git 2.3.10 Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.3.10.txt | 18 ++++++++++++++++++ Documentation/git.txt | 3 ++- GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 Documentation/RelNotes/2.3.10.txt diff --git a/Documentation/RelNotes/2.3.10.txt b/Documentation/RelNotes/2.3.10.txt new file mode 100644 index 0000000000..9d425d814d --- /dev/null +++ b/Documentation/RelNotes/2.3.10.txt @@ -0,0 +1,18 @@ +Git v2.3.10 Release Notes +========================= + +Fixes since v2.3.9 +------------------ + + * xdiff code we use to generate diffs is not prepared to handle + extremely large files. It uses "int" in many places, which can + overflow if we have a very large number of lines or even bytes in + our input files, for example. Cap the input size to soemwhere + around 1GB for now. + + * Some protocols (like git-remote-ext) can execute arbitrary code + found in the URL. The URLs that submodules use may come from + arbitrary sources (e.g., .gitmodules files in a remote + repository), and can hurt those who blindly enable recursive + fetch. Restrict the allowed protocols to well known and safe + ones. diff --git a/Documentation/git.txt b/Documentation/git.txt index 41a09cac7a..c06b923969 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v2.3.9/git.html[documentation for release 2.3.9] +* link:v2.3.10/git.html[documentation for release 2.3.10] * release notes for + link:RelNotes/2.3.10.txt[2.3.10], link:RelNotes/2.3.9.txt[2.3.9], link:RelNotes/2.3.8.txt[2.3.8], link:RelNotes/2.3.7.txt[2.3.7], diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 7577f66e97..0e353e80cc 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.3.9 +DEF_VER=v2.3.10 LF=' ' diff --git a/RelNotes b/RelNotes index 2f2927a251..25d9228ac5 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.3.9.txt \ No newline at end of file +Documentation/RelNotes/2.3.10.txt \ No newline at end of file From a2558fb8e1e387b630312311e1d22c95663da5d0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 28 Sep 2015 15:29:54 -0700 Subject: [PATCH 10/12] Git 2.4.10 Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.4.10.txt | 18 ++++++++++++++++++ Documentation/git.txt | 3 ++- GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 Documentation/RelNotes/2.4.10.txt diff --git a/Documentation/RelNotes/2.4.10.txt b/Documentation/RelNotes/2.4.10.txt new file mode 100644 index 0000000000..8621199bc6 --- /dev/null +++ b/Documentation/RelNotes/2.4.10.txt @@ -0,0 +1,18 @@ +Git v2.4.10 Release Notes +========================= + +Fixes since v2.4.9 +------------------ + + * xdiff code we use to generate diffs is not prepared to handle + extremely large files. It uses "int" in many places, which can + overflow if we have a very large number of lines or even bytes in + our input files, for example. Cap the input size to soemwhere + around 1GB for now. + + * Some protocols (like git-remote-ext) can execute arbitrary code + found in the URL. The URLs that submodules use may come from + arbitrary sources (e.g., .gitmodules files in a remote + repository), and can hurt those who blindly enable recursive + fetch. Restrict the allowed protocols to well known and safe + ones. diff --git a/Documentation/git.txt b/Documentation/git.txt index 5826bd9771..a405e4f2e7 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v2.4.9/git.html[documentation for release 2.4.9] +* link:v2.4.10/git.html[documentation for release 2.4.10] * release notes for + link:RelNotes/2.4.10.txt[2.4.10], link:RelNotes/2.4.9.txt[2.4.9], link:RelNotes/2.4.8.txt[2.4.8], link:RelNotes/2.4.7.txt[2.4.7], diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 38e296b311..859e14c1df 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.4.9 +DEF_VER=v2.4.10 LF=' ' diff --git a/RelNotes b/RelNotes index 3e8a59f846..50e4b25973 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.4.9.txt \ No newline at end of file +Documentation/RelNotes/2.4.10.txt \ No newline at end of file From 24358560c3c0ab51c9ef8178d99f46711716f6c0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 28 Sep 2015 15:26:49 -0700 Subject: [PATCH 11/12] Git 2.5.4 Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.5.4.txt | 18 ++++++++++++++++++ Documentation/git.txt | 3 ++- GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 Documentation/RelNotes/2.5.4.txt diff --git a/Documentation/RelNotes/2.5.4.txt b/Documentation/RelNotes/2.5.4.txt new file mode 100644 index 0000000000..a5e8477a4a --- /dev/null +++ b/Documentation/RelNotes/2.5.4.txt @@ -0,0 +1,18 @@ +Git v2.5.4 Release Notes +======================== + +Fixes since v2.5.4 +------------------ + + * xdiff code we use to generate diffs is not prepared to handle + extremely large files. It uses "int" in many places, which can + overflow if we have a very large number of lines or even bytes in + our input files, for example. Cap the input size to soemwhere + around 1GB for now. + + * Some protocols (like git-remote-ext) can execute arbitrary code + found in the URL. The URLs that submodules use may come from + arbitrary sources (e.g., .gitmodules files in a remote + repository), and can hurt those who blindly enable recursive + fetch. Restrict the allowed protocols to well known and safe + ones. diff --git a/Documentation/git.txt b/Documentation/git.txt index b2d88688aa..1a262757dc 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v2.5.3/git.html[documentation for release 2.5.3] +* link:v2.5.4/git.html[documentation for release 2.5.4] * release notes for + link:RelNotes/2.5.4.txt[2.5.4], link:RelNotes/2.5.3.txt[2.5.3], link:RelNotes/2.5.2.txt[2.5.2], link:RelNotes/2.5.1.txt[2.5.1], diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 7915077d2a..998786939b 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.5.3 +DEF_VER=v2.5.4 LF=' ' diff --git a/RelNotes b/RelNotes index 01910c5246..cdb1b4853d 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.5.3.txt \ No newline at end of file +Documentation/RelNotes/2.5.4.txt \ No newline at end of file From 22f698cb188243b313e024d618283e0293e37140 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 28 Sep 2015 19:19:27 -0700 Subject: [PATCH 12/12] Git 2.6.1 Signed-off-by: Junio C Hamano --- Documentation/RelNotes/2.6.1.txt | 18 ++++++++++++++++++ Documentation/git.txt | 3 ++- GIT-VERSION-GEN | 2 +- RelNotes | 2 +- 4 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 Documentation/RelNotes/2.6.1.txt diff --git a/Documentation/RelNotes/2.6.1.txt b/Documentation/RelNotes/2.6.1.txt new file mode 100644 index 0000000000..1e51363e3c --- /dev/null +++ b/Documentation/RelNotes/2.6.1.txt @@ -0,0 +1,18 @@ +Git v2.6.1 Release Notes +======================== + +Fixes since v2.6 +---------------- + + * xdiff code we use to generate diffs is not prepared to handle + extremely large files. It uses "int" in many places, which can + overflow if we have a very large number of lines or even bytes in + our input files, for example. Cap the input size to soemwhere + around 1GB for now. + + * Some protocols (like git-remote-ext) can execute arbitrary code + found in the URL. The URLs that submodules use may come from + arbitrary sources (e.g., .gitmodules files in a remote + repository), and can hurt those who blindly enable recursive + fetch. Restrict the allowed protocols to well known and safe + ones. diff --git a/Documentation/git.txt b/Documentation/git.txt index f9a7fb94c5..1a42631117 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v2.6.0/git.html[documentation for release 2.6] +* link:v2.6.1/git.html[documentation for release 2.6.1] * release notes for + link:RelNotes/2.6.1.txt[2.6.1], link:RelNotes/2.6.0.txt[2.6]. * link:v2.5.4/git.html[documentation for release 2.5.4] diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 97f58d1dbb..e1aba8533f 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.6.0 +DEF_VER=v2.6.1 LF=' ' diff --git a/RelNotes b/RelNotes index 84a20c84c6..def6ebd430 120000 --- a/RelNotes +++ b/RelNotes @@ -1 +1 @@ -Documentation/RelNotes/2.6.0.txt \ No newline at end of file +Documentation/RelNotes/2.6.1.txt \ No newline at end of file