Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
Tor
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
sergi
Tor
Commits
8f11642c
Commit
8f11642c
authored
14 years ago
by
Nick Mathewson
Browse files
Options
Downloads
Plain Diff
Merge branch 'bug2324_uncompress' into maint-0.2.1
parents
50b06a2b
1fcfc186
Branches
Branches containing commit
Tags
Tags containing commit
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
changes/bug2324_uncompress
+5
-0
5 additions, 0 deletions
changes/bug2324_uncompress
src/common/torgzip.c
+58
-2
58 additions, 2 deletions
src/common/torgzip.c
with
63 additions
and
2 deletions
changes/bug2324_uncompress
0 → 100644
+
5
−
0
View file @
8f11642c
o Major bugfixes (security):
- Prevent a DoS attack by disallowing any zlib-compressed data
whose compression factor is implausibly high. Fixes the
second part of bug2324; found by doors.
This diff is collapsed.
Click to expand it.
src/common/torgzip.c
+
58
−
2
View file @
8f11642c
...
...
@@ -57,6 +57,33 @@ method_bits(compress_method_t method)
return
method
==
GZIP_METHOD
?
15
+
16
:
15
;
}
/* These macros define the maximum allowable compression factor. Anything of
* size greater than CHECK_FOR_COMPRESSION_BOMB_AFTER is not allowed to
* have an uncompression factor (uncompressed size:compressed size ratio) of
* any greater than MAX_UNCOMPRESSION_FACTOR.
*
* Picking a value for MAX_UNCOMPRESSION_FACTOR is a trade-off: we want it to
* be small to limit the attack multiplier, but we also want it to be large
* enough so that no legitimate document --even ones we might invent in the
* future -- ever compresses by a factor of greater than
* MAX_UNCOMPRESSION_FACTOR. Within those parameters, there's a reasonably
* large range of possible values. IMO, anything over 8 is probably safe; IMO
* anything under 50 is probably sufficient.
*/
#define MAX_UNCOMPRESSION_FACTOR 25
#define CHECK_FOR_COMPRESSION_BOMB_AFTER (1024*64)
/** Return true if uncompressing an input of size <b>in_size</b> to an input
* of size at least <b>size_out</b> looks like a compression bomb. */
static
int
is_compression_bomb
(
size_t
size_in
,
size_t
size_out
)
{
if
(
size_in
==
0
||
size_out
<
CHECK_FOR_COMPRESSION_BOMB_AFTER
)
return
0
;
return
(
size_out
/
size_in
>
MAX_UNCOMPRESSION_FACTOR
);
}
/** Given <b>in_len</b> bytes at <b>in</b>, compress them into a newly
* allocated buffer, using the method described in <b>method</b>. Store the
* compressed string in *<b>out</b>, and its length in *<b>out_len</b>.
...
...
@@ -159,6 +186,12 @@ tor_gzip_compress(char **out, size_t *out_len,
}
tor_free
(
stream
);
if
(
is_compression_bomb
(
*
out_len
,
in_len
))
{
log_warn
(
LD_BUG
,
"We compressed something and got an insanely high "
"compression factor; other Tors would think this was a zlib bomb."
);
goto
err
;
}
return
0
;
err:
if
(
stream
)
{
...
...
@@ -223,7 +256,7 @@ tor_gzip_uncompress(char **out, size_t *out_len,
out_size
=
in_len
*
2
;
/* guess 50% compression. */
if
(
out_size
<
1024
)
out_size
=
1024
;
if
(
out_size
>
UINT_MAX
)
if
(
out_size
>=
SIZE_T_CEILING
||
out_size
>
UINT_MAX
)
goto
err
;
*
out
=
tor_malloc
(
out_size
);
...
...
@@ -263,7 +296,16 @@ tor_gzip_uncompress(char **out, size_t *out_len,
old_size
=
out_size
;
out_size
*=
2
;
if
(
out_size
<
old_size
)
{
log_warn
(
LD_GENERAL
,
"Size overflow in compression."
);
log_warn
(
LD_GENERAL
,
"Size overflow in uncompression."
);
goto
err
;
}
if
(
is_compression_bomb
(
in_len
,
out_size
))
{
log_warn
(
LD_GENERAL
,
"Input looks like a possible zlib bomb; "
"not proceeding."
);
goto
err
;
}
if
(
out_size
>=
SIZE_T_CEILING
)
{
log_warn
(
LD_BUG
,
"Hit SIZE_T_CEILING limit while uncompressing."
);
goto
err
;
}
*
out
=
tor_realloc
(
*
out
,
out_size
);
...
...
@@ -329,6 +371,11 @@ detect_compression_method(const char *in, size_t in_len)
struct
tor_zlib_state_t
{
struct
z_stream_s
stream
;
int
compress
;
/* Number of bytes read so far. Used to detect zlib bombs. */
size_t
input_so_far
;
/* Number of bytes written so far. Used to detect zlib bombs. */
size_t
output_so_far
;
};
/** Construct and return a tor_zlib_state_t object using <b>method</b>. If
...
...
@@ -395,11 +442,20 @@ tor_zlib_process(tor_zlib_state_t *state,
err
=
inflate
(
&
state
->
stream
,
finish
?
Z_FINISH
:
Z_SYNC_FLUSH
);
}
state
->
input_so_far
+=
state
->
stream
.
next_in
-
((
unsigned
char
*
)
*
in
);
state
->
output_so_far
+=
state
->
stream
.
next_out
-
((
unsigned
char
*
)
*
out
);
*
out
=
(
char
*
)
state
->
stream
.
next_out
;
*
out_len
=
state
->
stream
.
avail_out
;
*
in
=
(
const
char
*
)
state
->
stream
.
next_in
;
*
in_len
=
state
->
stream
.
avail_in
;
if
(
!
state
->
compress
&&
is_compression_bomb
(
state
->
input_so_far
,
state
->
output_so_far
))
{
log_warn
(
LD_DIR
,
"Possible zlib bomb; abandoning stream."
);
return
TOR_ZLIB_ERR
;
}
switch
(
err
)
{
case
Z_STREAM_END
:
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment