Too deep delta chains can cause stack overflow in get_base_data(). Set
a hard limit so that index-pack does not run out of stack. Also stop
people from producing such a long delta chains using "pack-object
--depth=<too large>"
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
I used to make very long delta chains and triggered this in index-pack.
I did not care reporting because it's my fault anyway. Think again,
index-pack is called at server side and a malicious client can
trigger this. This patch does not improve the situation much, but at
least we won't get sigsegv at server side.
builtin/index-pack.c | 12 ++++++++++--
builtin/pack-objects.c | 3 +++
pack.h | 2 ++
3 files changed, 15 insertions(+), 2 deletions(-)
@@ -504,13 +504,16 @@ static int is_delta_type(enum object_type type)return(type==OBJ_REF_DELTA||type==OBJ_OFS_DELTA);}-staticvoid*get_base_data(structbase_data*c)+staticvoid*get_base_data_1(structbase_data*c,intdepth){+if(depth>MAX_DELTA_DEPTH)+die("index-pack: too long delta chain");+if(!c->data){structobject_entry*obj=c->obj;if(is_delta_type(obj->type)){-void*base=get_base_data(c->base);+void*base=get_base_data_1(c->base,depth+1);void*raw=get_data_from_pack(obj);c->data=patch_delta(base,c->base->size,
From: Erik Faye-Lund <hidden> Date: 2016-06-15 22:52:34
2011/12/5 Nguyễn Thái Ngọc Duy [off-list ref]:
Too deep delta chains can cause stack overflow in get_base_data(). Set
a hard limit so that index-pack does not run out of stack. Also stop
people from producing such a long delta chains using "pack-object
--depth=<too large>"
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
I used to make very long delta chains and triggered this in index-pack.
I did not care reporting because it's my fault anyway. Think again,
index-pack is called at server side and a malicious client can
trigger this. This patch does not improve the situation much, but at
least we won't get sigsegv at server side.
Wouldn't it make more sense to make the limit a config option rather
than a hard-coded value of 128 (which seems arbitrary to me)? After
all, different platforms have different stack-limitations...
Too deep delta chains can cause stack overflow in get_base_data(). Set
a hard limit so that index-pack does not run out of stack. Also stop
people from producing such a long delta chains using "pack-object
--depth=<too large>"
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
I used to make very long delta chains and triggered this in index-pack.
I did not care reporting because it's my fault anyway. Think again,
index-pack is called at server side and a malicious client can
trigger this. This patch does not improve the situation much, but at
least we won't get sigsegv at server side.
Wouldn't it make more sense to make the limit a config option rather
than a hard-coded value of 128 (which seems arbitrary to me)? After
all, different platforms have different stack-limitations...
Then it'd make more sense to make a compile time config based on
platform. We could have a config option that can override the default,
but I really don't see the point of making long delta chains.
--
Duy
From: Erik Faye-Lund <hidden> Date: 2016-06-15 22:52:34
On Tue, Dec 6, 2011 at 1:32 PM, Nguyen Thai Ngoc Duy [off-list ref] wrote:
2011/12/6 Erik Faye-Lund [off-list ref]:
quoted
2011/12/5 Nguyễn Thái Ngọc Duy [off-list ref]:
quoted
Too deep delta chains can cause stack overflow in get_base_data(). Set
a hard limit so that index-pack does not run out of stack. Also stop
people from producing such a long delta chains using "pack-object
--depth=<too large>"
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
I used to make very long delta chains and triggered this in index-pack.
I did not care reporting because it's my fault anyway. Think again,
index-pack is called at server side and a malicious client can
trigger this. This patch does not improve the situation much, but at
least we won't get sigsegv at server side.
Wouldn't it make more sense to make the limit a config option rather
than a hard-coded value of 128 (which seems arbitrary to me)? After
all, different platforms have different stack-limitations...
Then it'd make more sense to make a compile time config based on
platform.
Can how much stack each recursion use be calculated at compile-time?
If so, I agree with you.
We could have a config option that can override the default,
but I really don't see the point of making long delta chains.
Aha, I figured you _did_ see a point in this, because 128 seemed
excessive to me already. I was thinking more that some platforms can
have a much smaller stack than (I would expect to) fit in 128
recursions (I've worked relatively recently with platforms with as
small as a static 2k stack per process), so you might not be fixing
the issue for such platforms. But that's not really your
responsibility either ;)
On Tue, Dec 6, 2011 at 7:41 PM, Erik Faye-Lund [off-list ref] wrote:
quoted
quoted
Wouldn't it make more sense to make the limit a config option rather
than a hard-coded value of 128 (which seems arbitrary to me)? After
all, different platforms have different stack-limitations...
Then it'd make more sense to make a compile time config based on
platform.
Can how much stack each recursion use be calculated at compile-time?
If so, I agree with you.
No, but at least we know default stack size of each platform and can
make pretty good limit based on that.
quoted
We could have a config option that can override the default,
but I really don't see the point of making long delta chains.
Aha, I figured you _did_ see a point in this, because 128 seemed
excessive to me already. I was thinking more that some platforms can
have a much smaller stack than (I would expect to) fit in 128
recursions (I've worked relatively recently with platforms with as
small as a static 2k stack per process), so you might not be fixing
the issue for such platforms. But that's not really your
responsibility either ;)
Ah, I was thinking of an option that extends the limit, not shortens
it. Yes it makes sense in this case.
--
Duy
From: Michael Haggerty <hidden> Date: 2016-06-15 22:52:34
On 12/06/2011 01:17 PM, Erik Faye-Lund wrote:
2011/12/5 Nguyễn Thái Ngọc Duy [off-list ref]:
quoted
Too deep delta chains can cause stack overflow in get_base_data(). Set
a hard limit so that index-pack does not run out of stack. Also stop
people from producing such a long delta chains using "pack-object
--depth=<too large>"
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
I used to make very long delta chains and triggered this in index-pack.
I did not care reporting because it's my fault anyway. Think again,
index-pack is called at server side and a malicious client can
trigger this. This patch does not improve the situation much, but at
least we won't get sigsegv at server side.
Wouldn't it make more sense to make the limit a config option rather
than a hard-coded value of 128 (which seems arbitrary to me)? After
all, different platforms have different stack-limitations...
I'm confused: is the data only ever read by the same host that generated
it? Because if not, then the "creator" had better never be configured
to use a chain depth that the "reader" cannot handle. This in turn
imply that there should be a common limit that is supported by all git
clients and is a documented part of the protocol. (Or the code has to
be rewritten to use an explicit stack instead of recursion.)
Michael
--
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/
Too deep delta chains can cause stack overflow in get_base_data(). Set
a hard limit so that index-pack does not run out of stack. Also stop
people from producing such a long delta chains using "pack-object
--depth=<too large>"
Signed-off-by: Nguyễn Thái Ngọc Duy <redacted>
---
I used to make very long delta chains and triggered this in index-pack.
I did not care reporting because it's my fault anyway. Think again,
index-pack is called at server side and a malicious client can
trigger this. This patch does not improve the situation much, but at
least we won't get sigsegv at server side.
Wouldn't it make more sense to make the limit a config option rather
than a hard-coded value of 128 (which seems arbitrary to me)? After
all, different platforms have different stack-limitations...
I'm confused: is the data only ever read by the same host that generated
it?
index-pack is called at server side as part of a push. So in theory
the sending side can generate very long delta chains and bring down
the server side.
Because if not, then the "creator" had better never be configured
to use a chain depth that the "reader" cannot handle.
Normal creators (i.e. C Git) use default depth 50 so we should be safe.
This in turn
imply that there should be a common limit that is supported by all git
clients and is a documented part of the protocol. (Or the code has to
be rewritten to use an explicit stack instead of recursion.)
It's the implementation limitation, not the protocol. If the server
propagates error messages from index-pack back to client (I'm not
sure), then users can adjust --depth to be accepted by server. We
could negotiate the limit over the protocol but not sure we would want
to go that route.
The troubled code could be rewritten to avoid recursion. However long
delta chains may degrade performance, I'd rather have support to split
long chains (which can be done with --depth at client already) instead
of just recursion elimination. This patch is simpler, so it would be
easier to back port it if someone wants to do so.
--
Duy
On Tue, Dec 6, 2011 at 07:30, Nguyen Thai Ngoc Duy [off-list ref] wrote:
index-pack is called at server side as part of a push. So in theory
the sending side can generate very long delta chains and bring down
the server side.
It is also called at client side during fetch. So in theory the server
can produce very long delta chains and take down a client.
quoted
Because if not, then the "creator" had better never be configured
to use a chain depth that the "reader" cannot handle.
Normal creators (i.e. C Git) use default depth 50 so we should be safe.
JGit is also a "normal creator", and it sometimes produces chains
deeper than 50. Junio identified a 255 deep chain a week or two ago.
Some people have repacked their repositories very aggressively with
deeper chains when they are trying to optimize for space and don't
access historical revisions very often. I doubt anyone has packed
deeper than 120ish intentionally... but we shouldn't assume that in
the code.
quoted
This in turn
imply that there should be a common limit that is supported by all git
clients and is a documented part of the protocol. (Or the code has to
be rewritten to use an explicit stack instead of recursion.)
It's the implementation limitation, not the protocol. If the server
propagates error messages from index-pack back to client (I'm not
sure), then users can adjust --depth to be accepted by server. We
could negotiate the limit over the protocol but not sure we would want
to go that route.
What about clients fetching from a server? The client can't change the
depth the server sends it.
The troubled code could be rewritten to avoid recursion. However long
delta chains may degrade performance, I'd rather have support to split
long chains (which can be done with --depth at client already) instead
of just recursion elimination. This patch is simpler, so it would be
easier to back port it if someone wants to do so.
JGit long ago changed its IndexPack routine to use a manually managed
heap based stack instead of recursion, making it immune from
overrunning the stack due to a long delta chain. That is probably the
cleaner route. But you also have to fix sha1_file.c and its recursion
based unpacking of a delta chain... again which JGit fixed a long time
ago.
From: Jeff King <hidden> Date: 2016-06-15 22:52:34
On Tue, Dec 06, 2011 at 10:12:54AM -0800, Shawn O. Pearce wrote:
quoted
Normal creators (i.e. C Git) use default depth 50 so we should be safe.
JGit is also a "normal creator", and it sometimes produces chains
deeper than 50. Junio identified a 255 deep chain a week or two ago.
Some people have repacked their repositories very aggressively with
deeper chains when they are trying to optimize for space and don't
access historical revisions very often. I doubt anyone has packed
deeper than 120ish intentionally... but we shouldn't assume that in
the code.
"git gc --aggressive" will set the depth to 250.
-Peff