summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <gitster@pobox.com>2016-09-08 21:49:47 -0700
committerJunio C Hamano <gitster@pobox.com>2016-09-08 21:49:47 -0700
commitda3b6f06e1224c9b8f5281a812731ef385ac4dc6 (patch)
tree75847482d3e90a71f07e30fff7e2dfd5239b3273
parent452a9073ba9f1fb157b3e5710b718aaf802e7631 (diff)
parentc08db5a2d0d5c0cf371168e621d5929005b1abf8 (diff)
downloadgit-da3b6f06e1224c9b8f5281a812731ef385ac4dc6.tar.gz
Merge branch 'cc/receive-pack-limit'
An incoming "git push" that attempts to push too many bytes can now be rejected by setting a new configuration variable at the receiving end. * cc/receive-pack-limit: receive-pack: allow a maximum input size to be specified unpack-objects: add --max-input-size=<size> option index-pack: add --max-input-size=<size> option
-rw-r--r--Documentation/config.txt6
-rw-r--r--Documentation/git-index-pack.txt2
-rw-r--r--Documentation/git-receive-pack.txt3
-rw-r--r--Documentation/git-unpack-objects.txt3
-rw-r--r--builtin/index-pack.c5
-rw-r--r--builtin/receive-pack.c12
-rw-r--r--builtin/unpack-objects.c7
-rwxr-xr-xt/t5546-receive-limits.sh55
8 files changed, 93 insertions, 0 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 0bcb6790d6..8a115b3702 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2517,6 +2517,12 @@ receive.unpackLimit::
especially on slow filesystems. If not set, the value of
`transfer.unpackLimit` is used instead.
+receive.maxInputSize::
+ If the size of the incoming pack stream is larger than this
+ limit, then git-receive-pack will error out, instead of
+ accepting the pack file. If not set or set to 0, then the size
+ is unlimited.
+
receive.denyDeletes::
If set to true, git-receive-pack will deny a ref update that deletes
the ref. Use this to prevent such a ref deletion via a push.
diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt
index 7a4e055520..1b4b65d665 100644
--- a/Documentation/git-index-pack.txt
+++ b/Documentation/git-index-pack.txt
@@ -87,6 +87,8 @@ OPTIONS
Specifying 0 will cause Git to auto-detect the number of CPU's
and use maximum 3 threads.
+--max-input-size=<size>::
+ Die, if the pack is larger than <size>.
Note
----
diff --git a/Documentation/git-receive-pack.txt b/Documentation/git-receive-pack.txt
index 000ee8dba2..0ccd5fbc78 100644
--- a/Documentation/git-receive-pack.txt
+++ b/Documentation/git-receive-pack.txt
@@ -33,6 +33,9 @@ post-update hooks found in the Documentation/howto directory.
option, which tells it if updates to a ref should be denied if they
are not fast-forwards.
+A number of other receive.* config options are available to tweak
+its behavior, see linkgit:git-config[1].
+
OPTIONS
-------
<directory>::
diff --git a/Documentation/git-unpack-objects.txt b/Documentation/git-unpack-objects.txt
index 3e887d1610..b3de50d710 100644
--- a/Documentation/git-unpack-objects.txt
+++ b/Documentation/git-unpack-objects.txt
@@ -44,6 +44,9 @@ OPTIONS
--strict::
Don't write objects with broken content or links.
+--max-input-size=<size>::
+ Die, if the pack is larger than <size>.
+
GIT
---
Part of the linkgit:git[1] suite
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 1d2ea583a4..4a8b4aebba 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -87,6 +87,7 @@ static struct progress *progress;
static unsigned char input_buffer[4096];
static unsigned int input_offset, input_len;
static off_t consumed_bytes;
+static off_t max_input_size;
static unsigned deepest_delta;
static git_SHA_CTX input_ctx;
static uint32_t input_crc32;
@@ -297,6 +298,8 @@ static void use(int bytes)
if (signed_add_overflows(consumed_bytes, bytes))
die(_("pack too large for current definition of off_t"));
consumed_bytes += bytes;
+ if (max_input_size && consumed_bytes > max_input_size)
+ die(_("pack exceeds maximum allowed size"));
}
static const char *open_pack_file(const char *pack_name)
@@ -1714,6 +1717,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
opts.off32_limit = strtoul(c+1, &c, 0);
if (*c || opts.off32_limit & 0x80000000)
die(_("bad %s"), arg);
+ } else if (skip_prefix(arg, "--max-input-size=", &arg)) {
+ max_input_size = strtoumax(arg, NULL, 10);
} else
usage(index_pack_usage);
continue;
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 011db00d31..f1ce05ce28 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -46,6 +46,7 @@ static int transfer_unpack_limit = -1;
static int advertise_atomic_push = 1;
static int advertise_push_options;
static int unpack_limit = 100;
+static off_t max_input_size;
static int report_status;
static int use_sideband;
static int use_atomic;
@@ -212,6 +213,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
return 0;
}
+ if (strcmp(var, "receive.maxinputsize") == 0) {
+ max_input_size = git_config_int64(var, value);
+ return 0;
+ }
+
return git_default_config(var, value, cb);
}
@@ -1648,6 +1654,9 @@ static const char *unpack(int err_fd, struct shallow_info *si)
if (fsck_objects)
argv_array_pushf(&child.args, "--strict%s",
fsck_msg_types.buf);
+ if (max_input_size)
+ argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
+ (uintmax_t)max_input_size);
child.no_stdout = 1;
child.err = err_fd;
child.git_cmd = 1;
@@ -1676,6 +1685,9 @@ static const char *unpack(int err_fd, struct shallow_info *si)
fsck_msg_types.buf);
if (!reject_thin)
argv_array_push(&child.args, "--fix-thin");
+ if (max_input_size)
+ argv_array_pushf(&child.args, "--max-input-size=%"PRIuMAX,
+ (uintmax_t)max_input_size);
child.out = -1;
child.err = err_fd;
child.git_cmd = 1;
diff --git a/builtin/unpack-objects.c b/builtin/unpack-objects.c
index 172470bf24..4532aa0831 100644
--- a/builtin/unpack-objects.c
+++ b/builtin/unpack-objects.c
@@ -19,6 +19,7 @@ static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict]
static unsigned char buffer[4096];
static unsigned int offset, len;
static off_t consumed_bytes;
+static off_t max_input_size;
static git_SHA_CTX ctx;
static struct fsck_options fsck_options = FSCK_OPTIONS_STRICT;
@@ -87,6 +88,8 @@ static void use(int bytes)
if (signed_add_overflows(consumed_bytes, bytes))
die("pack too large for current definition of off_t");
consumed_bytes += bytes;
+ if (max_input_size && consumed_bytes > max_input_size)
+ die(_("pack exceeds maximum allowed size"));
}
static void *get_data(unsigned long size)
@@ -550,6 +553,10 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix)
len = sizeof(*hdr);
continue;
}
+ if (skip_prefix(arg, "--max-input-size=", &arg)) {
+ max_input_size = strtoumax(arg, NULL, 10);
+ continue;
+ }
usage(unpack_usage);
}
diff --git a/t/t5546-receive-limits.sh b/t/t5546-receive-limits.sh
new file mode 100755
index 0000000000..10cb0be2b7
--- /dev/null
+++ b/t/t5546-receive-limits.sh
@@ -0,0 +1,55 @@
+#!/bin/sh
+
+test_description='check receive input limits'
+. ./test-lib.sh
+
+# Let's run tests with different unpack limits: 1 and 10000
+# When the limit is 1, `git receive-pack` will call `git index-pack`.
+# When the limit is 10000, `git receive-pack` will call `git unpack-objects`.
+
+test_pack_input_limit () {
+ case "$1" in
+ index) unpack_limit=1 ;;
+ unpack) unpack_limit=10000 ;;
+ esac
+
+ test_expect_success 'prepare destination repository' '
+ rm -fr dest &&
+ git --bare init dest
+ '
+
+ test_expect_success "set unpacklimit to $unpack_limit" '
+ git --git-dir=dest config receive.unpacklimit "$unpack_limit"
+ '
+
+ test_expect_success 'setting receive.maxInputSize to 512 rejects push' '
+ git --git-dir=dest config receive.maxInputSize 512 &&
+ test_must_fail git push dest HEAD
+ '
+
+ test_expect_success 'bumping limit to 4k allows push' '
+ git --git-dir=dest config receive.maxInputSize 4k &&
+ git push dest HEAD
+ '
+
+ test_expect_success 'prepare destination repository (again)' '
+ rm -fr dest &&
+ git --bare init dest
+ '
+
+ test_expect_success 'lifting the limit allows push' '
+ git --git-dir=dest config receive.maxInputSize 0 &&
+ git push dest HEAD
+ '
+}
+
+test_expect_success "create known-size (1024 bytes) commit" '
+ test-genrandom foo 1024 >one-k &&
+ git add one-k &&
+ test_commit one-k
+'
+
+test_pack_input_limit index
+test_pack_input_limit unpack
+
+test_done