Note: This is a beta release of Red Hat Bugzilla 5.0. The data contained within is a snapshot of the live data so any changes you make will not be reflected in the production Bugzilla. Also email is disabled so feel free to test any aspect of the site that you want. File any problems you find or give feedback here.
Bug 161925 - CVE-2005-2708 user code panics kernel in exec.c
Summary: CVE-2005-2708 user code panics kernel in exec.c
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 3
Classification: Red Hat
Component: kernel
Version: 3.0
Hardware: x86_64
OS: Linux
medium
high
Target Milestone: ---
Assignee: Dave Anderson
QA Contact: Brian Brock
URL:
Whiteboard: source=bz,reported=20050628,public=20...
Depends On:
Blocks: 168424
TreeView+ depends on / blocked
 
Reported: 2005-06-28 14:56 UTC by blossom
Modified: 2007-11-30 22:07 UTC (History)
3 users (show)

Fixed In Version: RHSA-2006-0140
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2006-01-19 15:59:49 UTC


Attachments (Terms of Use)
fixes bug in exec.c which now checks for return code during error condition (deleted)
2005-06-28 14:56 UTC, blossom
no flags Details | Diff
Final patch (deleted)
2005-11-24 08:50 UTC, Mark J. Cox
no flags Details | Diff


Links
System ID Priority Status Summary Last Updated
Red Hat Product Errata RHSA-2006:0140 normal SHIPPED_LIVE Important: kernel security update 2006-01-19 05:00:00 UTC

Description blossom 2005-06-28 14:56:07 UTC
Description of problem:
user code panics kernel in exec.c

Version-Release number of selected component (if applicable):
RHEL 3.0 Update 4

How reproducible:
Everytime

Steps to Reproduce:
1.
Symptom:
the following code
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

#define SIZE 1000000

int main (int argc, char **argv)
{
int i;
double sum = 0.0;
double t[SIZE];

for (i = 0; i < SIZE; i++)
{
  t[i] = 1.0 + 1.0*SIZE*rand()/(RAND_MAX+1.0) - RAND_MAX/2.0; }

for (i = 0; i > SIZE; i++)
{
  sum += t[i];
}

printf ("Moyenne = %lf\n", sum);

return 0;
}

2.compiled this way
gcc -o essai essai.c

3. on a node :
bash -c 'ulimit -v 100; ./essai'

then node panic:

 
Actual results:

tantal237 login: double fault: 0000
CPU 2
Pid: 3552, comm: modprobe Tainted: P
RIP: 0010:[<0000000000000000>]
RSP: 0000:0000000000000000  EFLAGS: 00010202
RAX: 0000000000000000 RBX: 0000000000000040 RCX: 0000000000000000
RDX: ffffffff80437560 RSI: 00000100bdaf7f08 RDI: ffffffff80437460
RBP: 0000010080008f40 R08: 0000000000000004 R09: 00000100bde77080
R10: 0000000000000000 R11: 0000000000000010 R12: 00000100e660a6c0
R13: 0000010081c2b280 R14: 0000010081c2b280 R15: 0000010080008ec0
FS:  0000002a95aca0a0(0000) GS:ffffffff805e79c0(0000) knlGS:00000000080c9760
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 00000000047a1000 CR4: 00000000000006e0

Call Trace:
Process modprobe (pid: 3552, stackpage=100bdaf5000)

Kernel panic: Fatal exception

Expected results:


Additional info:

Comment 1 blossom 2005-06-28 14:56:07 UTC
Created attachment 116064 [details]
fixes bug in exec.c which now checks for return code during error condition

Comment 2 Ernie Petrides 2005-06-28 17:53:05 UTC
Hello.  Firstly, the test program is irrelevant.  On RHEL3 U4, the following
command takes the code path in question (altered by the patch above):

  bash -c 'ulimit -v 100 ; /bin/date'

However, my x86 box simply prints an error on the console about failing to
load the interpreter for binfmt-464c.  Thus, the steps listed to reproduce
the problem are inadequate.

Please try to reproduce this problem on the latest released kernel (which
is version 2.4.21-32.0.1.EL, a post-U5 security erratum) that is untainted.
Also, please correct the hardware architecture of this bug report if you're
not using an x86-based system.

Thanks in advance.  -ernie


Comment 3 blossom 2005-06-28 18:49:48 UTC
Well, the problem is reproducible under RHEL 3 post update 5,  2.4.21-
32.0.1.EL kernel. We are using x86_64 system. Check whether the fix(attached) 
is fine

Regards
Girish

Comment 4 blossom 2005-06-28 18:53:37 UTC
Well, the problem is reproducible under RHEL 3 post update 5,  2.4.21-
32.0.1.EL kernel. We are using x86_64 system. Check whether the fix(attached) 
is fine

Regards
Girish

Comment 5 Ernie Petrides 2005-06-28 20:19:42 UTC
Fixing hardware field of BZ.  The patch in comment #1 is inappropriate
because since "retval" is always -ENOEXEC in that code path, it
effectively disables the call to request_module() every time.  DaveA
will try to reproduce this locally on an x86_64 system.

Comment 6 blossom 2005-08-26 12:31:24 UTC
Here is a better fix for the problem:

Regards
Girish

diff -uprN linux-2.4.21/fs/binfmt_elf.c linux-2.4.21n/fs/binfmt_elf.c
--- linux-2.4.21/fs/binfmt_elf.c        2005-08-26 02:34:17.000000000 +0530
+++ linux-2.4.21n/fs/binfmt_elf.c       2005-08-26 05:06:07.000000000 +0530
@@ -872,6 +872,7 @@ static int load_elf_binary(struct linux_
                        printk(KERN_ERR "Unable to load interpreter\n");
                        send_sig(SIGSEGV, current, 0);
                        retval = -ENOEXEC; /* Nobody gets to see this, but.. */
+                       memset(bprm->buf, 0, strlen(bprm->buf));
                        goto out_free_dentry;
                }
                reloc_func_desc = interp_load_addr;
diff -uprN linux-2.4.21/fs/exec.c linux-2.4.21n/fs/exec.c
--- linux-2.4.21/fs/exec.c      2005-08-26 02:34:19.000000000 +0530
+++ linux-2.4.21n/fs/exec.c     2005-08-26 06:04:03.000000000 +0530
@@ -1061,7 +1061,7 @@ int search_binary_handler(struct linux_b
                        if (printable(bprm->buf[0]) &&
                            printable(bprm->buf[1]) &&
                            printable(bprm->buf[2]) &&
-                           printable(bprm->buf[3]))
+                           printable(bprm->buf[3]) || !(bprm->buf[2]))
                                break; /* -ENOEXEC */
                        sprintf(modname, "binfmt-%04x", *(unsigned short *)(&bpr
m->buf[2]));
                        request_module(modname);



Comment 7 Dave Anderson 2005-08-30 15:39:45 UTC
Running on a RHEL3-U5'ish kernel (2.4.21-31+), a user process running this:

  $ bash -c 'ulimit -v 100 ; /bin/date' 

does cause a double fault in the same manner shown above, i.e., with the
RIP and RSP registers getting NULL'd out:

Unable to load interpreter
request_module[binfmt-464c]: waitpid(2304,...) failed, errno 512
double fault: 0000
CPU 1
Pid: 2304, comm: modprobe Not tainted
RIP: 0010:[<0000000000000000>]
RSP: 0000:0000000000000000  EFLAGS: 00010202
RAX: 0000000000000000 RBX: 0000000000000040 RCX: 0000000000000000
RDX: ffffffff80436c60 RSI: 000001011a849f08 RDI: ffffffff80436b60
RBP: 000001001658fc40 R08: 0000000000000004 R09: 000001011b975a80
R10: 0000000000000000 R11: 0000000000000010 R12: 000001001658fc40
R13: 000001001658fc40 R14: 00000100161d7cc4 R15: 000001011a848000
FS:  0000002a95ada0a0(0000) GS:ffffffff805e6600(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 000000001657f000 CR4: 00000000000006e0

Call Trace:  <EOE>
Process modprobe (pid: 2304, stackpage=1011a849000)





Comment 8 Dave Anderson 2005-08-30 16:14:43 UTC
Same with latest RHEL3-U6 (2.4.21-35):

Unable to load interpreter
request_module[binfmt-464c]: waitpid(2296,...) failed, errno 512
double fault: 0000
CPU 1
Pid: 2296, comm: modprobe Not tainted
RIP: 0010:[<0000000000000000>]
RSP: 0000:0000000000000000  EFLAGS: 00010202
RAX: 0000000000000000 RBX: 0000000000000040 RCX: 0000000000000000
RDX: ffffffff80437e60 RSI: 000001011887ff08 RDI: ffffffff80437d60
RBP: 000001001658fc40 R08: 000000000000002c R09: 000001011b8ae440
R10: 0000000000000000 R11: 0000000000000010 R12: 000001001658fc40
R13: 000001001658fc40 R14: 00000100161d6f04 R15: 000001011887e000
FS:  0000002a95ada0a0(0000) GS:ffffffff805e8080(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000000 CR3: 000000001657f000 CR4: 00000000000006e0

Call Trace:  <EOE>
Process modprobe (pid: 2296, stackpage=1011887f000)

It doesn't happen on i386 or ia64 systems.

Comment 9 Dave Anderson 2005-08-31 18:36:28 UTC
I don't particularly care for either patch suggestion.  The problem is
that load_elf_binary() -- which is trying to load a legitimate ELF binary,
is returning -ENOEXEC back to search_binary_handler() because load_elf_interp()
has returned a BAD_ADDR:

        if (elf_interpreter) {
                if (interpreter_type == INTERPRETER_AOUT)
                        elf_entry = load_aout_interp(&interp_ex,
                                                     interpreter);
                else
                        elf_entry = load_elf_interp(&interp_elf_ex,
                                                    interpreter,
                                                    &interp_load_addr);

                if (BAD_ADDR(elf_entry)) {
                        printk(KERN_ERR "Unable to load interpreter\n");
                        send_sig(SIGSEGV, current, 0);
                        retval = -ENOEXEC; /* Nobody gets to see this, but.. */
                        goto out_free_dentry;
                }
                reloc_func_desc = interp_load_addr;

                allow_write_access(interpreter);
                fput(interpreter);
                kfree(elf_interpreter);
        }

and *because* search_binary_handler() sees the -ENOEXEC, it kicks off the
attempt to load the bogus module.  And therein lies the problem, for whatever
reason, the modprobe process results in the double-fault, and the original
exec operation continues, and fails as it should.  But that all may be a red
herring, since ENOEXEC with respect to execve means: 

      ENOEXEC An  executable  is  not in a recognised format, is for the wrong
              architecture, or has some other format error that means it  can-
              not be executed.

However in this case, that's not at all true.  It's legitimate, but the attempt
to load the /lib64/ld-linux-x86-64.so.2 interpreter into the limited address
space fails, and load_elf_interp() returns -ENOMEM.  But the ENOMEM is "lost"
in the elf_entry variable.  However, if -ENOMEM is in fact returned back to
search_binary_handler(), it all works just fine.  ENOMEM with respect to execve
means:

       ENOMEM Insufficient kernel memory was available.

which isn't *exactly* what's going on here, but pretty close...

There's also the question of why the modprobe is failing, given that the
bogus module name doesn't exist.  You would think that shouldn't cause the
kernel to double-fault.  I mean do *all* of the request_module() calls in
the kernel require that the target module pre-exist?  Since the kernel
seems to handle it differently/successfully on at least i386 and ia64,
I haven't determined whether the request_module() is even attempted on those
architectures, or whether the operation fails in a different code path.



Comment 10 Dave Anderson 2005-09-01 14:18:01 UTC
Working on a patch that addresses both problems, i.e., having
load_elf_binary() return the proper errno value (ENOMEM), and
preventing the request_module() from double-faulting -- presumably
because the modprobe exec is reacting to the limited address
space inherited from the process calling request_module().

The ENOMEM return will fix this problem, but for ELF objects
only.  If a legitimate "odd" binfmt request did in fact come in,
and the user had done ulimit beforehand, then the oops would
still occur.

Thanks for the report -- and sorry for the delay.



Comment 14 Mark J. Cox 2005-09-19 09:44:04 UTC
For future bug reports which have can have a security consequence please follow
our procedure for reporting security issues, or at the least use the "Security
Sensitive Bug" checkbox.  http://www.redhat.com/security/team/contact/.

This is CAN-2005-2708

Comment 15 Ernie Petrides 2005-09-22 00:38:04 UTC
A fix for this problem has just been committed to the RHEL3 U7
patch pool this evening (in kernel version 2.4.21-37.3.EL).


Comment 16 dann frazier 2005-11-24 07:20:30 UTC
(In reply to comment #15)
> A fix for this problem has just been committed to the RHEL3 U7
> patch pool this evening (in kernel version 2.4.21-37.3.EL).
> 

Is this fix available publicly?

Comment 17 Mark J. Cox 2005-11-24 08:50:24 UTC
Created attachment 121437 [details]
Final patch

Note this issue only affects linux-2.4 and not linux-2.6 kernels.

Comment 19 Ernie Petrides 2005-11-28 23:48:31 UTC
In answer to comment #16, not yet.  The RHEL3 U7 beta candidate kernel
will probably be built later this week.


Comment 21 Ernie Petrides 2006-01-11 23:32:51 UTC
A fix for this problem has also been committed to the RHEL3 E7
patch pool this evening (in kernel version 2.4.21-37.0.1.EL).


Comment 23 Red Hat Bugzilla 2006-01-19 15:59:49 UTC
An advisory has been issued which should help the problem
described in this bug report. This report is therefore being
closed with a resolution of ERRATA. For more information
on the solution and/or where to find the updated files,
please follow the link below. You may reopen this bug report
if the solution does not work for you.

http://rhn.redhat.com/errata/RHSA-2006-0140.html



Note You need to log in before you can comment on or make changes to this bug.