From 635c5a8a92c8066412645b291817eadcc82d8f8f Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Mon, 13 Feb 2017 15:22:36 -0500 Subject: [PATCH 1/2] be sure to remember the changes file for #20384 --- changes/bug20384 | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 changes/bug20384 diff --git a/changes/bug20384 b/changes/bug20384 new file mode 100644 index 000000000..591015ad9 --- /dev/null +++ b/changes/bug20384 @@ -0,0 +1,10 @@ + o Major features (security fixes): + - Prevent a class of security bugs caused by treating the contents + of a buffer chunk as if they were a NUL-terminated string. At + least one such bug seems to be present in all currently used + versions of Tor, and would allow an attacker to remotely crash + most Tor instances, especially those compiled with extra compiler + hardening. With this defense in place, such bugs can't crash Tor, + though we should still fix them as they occur. Closes ticket + 20384 (TROVE-2016-10-001). + From 194e31057fbf07d6bdf4b62d26e1a9db334e5f1c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 7 Feb 2017 10:58:02 -0500 Subject: [PATCH 2/2] Avoid integer underflow in tor_version_compare. Fix for TROVE-2017-001 and bug 21278. (Note: Instead of handling signed ints "correctly", we keep the old behavior, except for the part where we would crash with -ftrapv.) --- changes/trove-2017-001.2 | 8 +++++++ src/or/routerparse.c | 49 ++++++++++++++++++++++++---------------- 2 files changed, 38 insertions(+), 19 deletions(-) create mode 100644 changes/trove-2017-001.2 diff --git a/changes/trove-2017-001.2 b/changes/trove-2017-001.2 new file mode 100644 index 000000000..3ef073cf9 --- /dev/null +++ b/changes/trove-2017-001.2 @@ -0,0 +1,8 @@ + o Major bugfixes (parsing): + - Fix an integer underflow bug when comparing malformed Tor versions. + This bug is harmless, except when Tor has been built with + --enable-expensive-hardening, which would turn it into a crash; + or on Tor 0.2.9.1-alpha through Tor 0.2.9.8, which were built with + -ftrapv by default. + Part of TROVE-2017-001. Fixes bug 21278; bugfix on + 0.0.8pre1. Found by OSS-Fuzz. diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 71373ce63..1243035f9 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -4545,26 +4545,37 @@ tor_version_compare(tor_version_t *a, tor_version_t *b) int i; tor_assert(a); tor_assert(b); - if ((i = a->major - b->major)) - return i; - else if ((i = a->minor - b->minor)) - return i; - else if ((i = a->micro - b->micro)) - return i; - else if ((i = a->status - b->status)) - return i; - else if ((i = a->patchlevel - b->patchlevel)) - return i; - else if ((i = strcmp(a->status_tag, b->status_tag))) - return i; - else if ((i = a->svn_revision - b->svn_revision)) - return i; - else if ((i = a->git_tag_len - b->git_tag_len)) - return i; - else if (a->git_tag_len) - return fast_memcmp(a->git_tag, b->git_tag, a->git_tag_len); + + /* We take this approach to comparison to ensure the same (bogus!) behavior + * on all inputs as we would have seen before bug #21278 was fixed. The + * only important difference here is that this method doesn't cause + * a signed integer underflow. + */ +#define CMP(field) do { \ + unsigned aval = (unsigned) a->field; \ + unsigned bval = (unsigned) b->field; \ + int result = (int) (aval - bval); \ + if (result < 0) \ + return -1; \ + else if (result > 0) \ + return 1; \ + } while (0) + + CMP(major); + CMP(minor); + CMP(micro); + CMP(status); + CMP(patchlevel); + if ((i = strcmp(a->status_tag, b->status_tag))) + return i; + CMP(svn_revision); + CMP(git_tag_len); + if (a->git_tag_len) + return fast_memcmp(a->git_tag, b->git_tag, a->git_tag_len); else - return 0; + return 0; + +#undef CMP } /** Return true iff versions a and b belong to the same series.