Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [day] [month] [year] [list]
Date: Wed, 2 Jul 2008 09:53:18 +0200
From: Tomas Hoger <thoger@...hat.com>
To: oss-security@...ts.openwall.com
Subject: More ruby integer overflows (rb_ary_fill / Array#fill)

Hi!

During the work on ruby updates, our ruby maintainer (Akira Tagoh) came
across some commits in the ruby SVN, that fix (or attempt to fix)
integer overflows in rb_ary_fill() - Array#fill method.

This problem is probably less severe than recent Drew Yao's issues, as
it's probably less likely this is exposed to an untrusted input in some
random ruby application.

First, ~9 months ago following change was added:
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=13397

The idea of this fix was to prevent "end = beg + len;" to overflow and
end ending up being negative, causing a bypass of the memory
reallocation below.

This was insufficient, as end is array length, but size of each array
element is more than 1byte.  So you can only have arrays up to
ARY_MAX_SIZE elements (added in the fixes for recent integer
overflows reported by Drew Yao).  So you could still get an overflow
during the array fill below or cause integer overflow in REALLOC_N.

This was further addressed in:
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17688

However, even with that fix, it was still possible to trigger overflow
by specifying a beg index greater than ARY_MAX_SIZE.  Following check
"if (len > ARY_MAX_SIZE - beg)" gets evaluated as unsigned (search for
unsigned sizeof(VALUE) in ARY_MAX_SIZE definition) and you could get
negative end again.

This problem was fixed quickly after being reported upstream in:
http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17756

We have assigned CVE-2008-2376 to this issue.  If you want to claim
you have fixed CVE-2008-2376, please make sure you have all fixes up to
r17756.

Note: I've quickly reviewed other uses of ARY_MAX_SIZE in 1.8.6-p230.
There is only one case when value is subtracted from ARY_MAX_SIZE
without being explicitly checked not to be greater than ARY_MAX_SIZE:

  if (beg > ARY_MAX_SIZE - rlen) {

However, rlen is the length of some existing array, hence can not be
more than ARY_MAX_SIZE.

-- 
Tomas Hoger / Red Hat Security Response Team

Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Powered by Openwall GNU/*/Linux - Powered by OpenVZ