Bug 804792

Summary: sha512-crypt.c usage of alloca() unbounded
Product: [Fedora] Fedora Reporter: Russell Bryant <rbryant>
Component: glibcAssignee: Jeff Law <law>
Status: CLOSED RAWHIDE QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: high Docs Contact:
Priority: unspecified    
Version: 16CC: dprince, fweimer, jlieskov, pbrady, rbryant, security-response-team
Target Milestone: ---Keywords: Security
Target Release: ---   
Hardware: x86_64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2012-03-29 18:50:36 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:

Description Russell Bryant 2012-03-19 19:32:43 UTC
Description of problem:

We received a report of a remotely exploitable crash vulnerability in OpenStack (http://www.openstack.org).  The root cause turned out to be in glibc, when a password of excessive length made it down to sha512 crypt and resulted in an unbounded alloca() that exhausted the stack.

Here is an abbreviated demonstration of the bug in Python as it occurred in OpenStack (with python-passlib installed):

    import passlib.hash

    pw_utf8 = ('a' * 9999999).encode('utf-8')
    pw_hash = passlib.hash.sha512_crypt.encrypt(pw_utf8)
    passlib.hash.sha512_crypt.verify(pw_utf8, pw_hash)

It can also be reproduced using the crypt Python module directly:

    import crypt

    pw_utf8 = ('a' * 9999999).encode('utf-8')
    crypt.crypt(pw_utf8, '$6$' + '.'*16)

Both of these examples will result in a seg fault that resembles the following:

Program received signal SIGSEGV, Segmentation fault.
__sha512_crypt_r (key=0x7fffeb1db034 'a' <repeats 200 times>...,
salt=0x7f9bec "dWs9ZDUtzP4oF/03$",
   buffer=0x7a8a40
"$6$rounds=1000$test$2M/Lx6MtobqjLjobw0Wmo4Q5OFx5nVLJvmgseatA6oMnyWeBdRDx4DU.1H3eGmse6pgsOgDisWBGI5c7TZauS0")
at sha512-crypt.c:153
153           key = copied_key =

(gdb) list
148       key_len = strlen (key);
149
150       if ((key - (char *) 0) % __alignof__ (uint64_t) != 0)
151         {
152           char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t));
153           key = copied_key =
154             memcpy (tmp + __alignof__ (uint64_t)
155                     - (tmp - (char *) 0) % __alignof__ (uint64_t),
156                     key, key_len);
157           assert ((key - (char *) 0) % __alignof__ (uint64_t) == 0);


Version-Release number of selected component (if applicable):

glibc-2.14.90-24.fc16.6.x86_64

Comment 2 Russell Bryant 2012-03-19 20:25:44 UTC
Thanks for the archive link.  I meant to post that ... pbrady pointed that out to me before I posted this.  It wasn't clear if the issue was ever reported anywhere and the code appears to still be the same, so I figure it should be reported.

Also, the original reporter of this issue to OpenStack was Dan Prince (dprince).

Comment 3 Jan Lieskovsky 2012-03-20 13:23:43 UTC
Though we understand the potential negative implications, this deficiency might have on packages / code using glibc's sha512-crypt module's routines, we would not classify this bug to be a security issue in glibc.

Explanation:
The currently seen behaviour is expected in the sense of the way how alloca() system call is intended to be used (to allocate space in the stack frame of the caller and automatically free the allocated space when the function from which alloca() was called returned). When the size of memory to be allocated in this temporary space would not fit into the stack frame of the caller (IOW by attempt to write at memory location past the stack frame of the caller), it is expected the application to be terminated. The only consequence of this behaviour (when very long password strings are used) is the termination (crash) of the application.

Comment 4 Jeff Law 2012-03-23 20:53:28 UTC
But isn't blowing out the stack subject to the kind of attacks seen in CVE-2012-0864 where passing a "clever" value to alloca causes the stack pointer to point into the heap and the potentially opening up all kinds of interesting attack vectors.

Comment 5 Jeff Law 2012-03-29 18:50:36 UTC
Fixed in rawhide, f17 & rhel 7 trees.  Not currently planning to backport to f15, f16, rhel5 or rhel6.

Comment 6 Tomas Hoger 2012-03-30 10:19:39 UTC
OpenStack Keystone was changed to limit the length of the passwords it processes - see bug #805551.

glibc upstream list on the Jeff's patch to make crypt implementation use malloc instead of alloca for long inputs:

http://sourceware.org/ml/libc-alpha/2012-03/msg01138.html
http://sourceware.org/ml/libc-alpha/2012-03/msg01158.html