OSDN Git Service
[PATCH] x86-64: user code panics kernel in exec.c (CVE-2005-2708)
There seems to be a local DoS in exec on AMD64 / linux 2.4
when the system is under memory pressure.
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=161925
Comment #9 From Dave Anderson on 2005-08-31 14:36 EST
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.