Bug 39222

Summary: Timerace in sys_execve when copying argv/env data from userspace
Product: Other Reporter: me
Component: OtherAssignee: other_other
Status: NEW ---    
Severity: normal CC: xerofoify
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 3.0.0-rc2 Subsystem:
Regression: No Bisected commit-id:

Description me 2011-07-12 14:53:29 UTC
Seems to be historic, but not exploitable timerace (POC available).

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=fs/exec.c;h=6075a1e727aee13dd3cd492b61d55edd81ee258e;hb=HEAD

In

472 static int copy_strings(int argc, struct user_arg_ptr argv,
473                         struct linux_binprm *bprm)
474 {

length of new argv/envp is determined using

490                 len = strnlen_user(str, MAX_ARG_STRLEN);

and used afterwards for copy. In between the data can be modified by removing the last 0-byte or adding more 0-bytes. The consequence is arg n, n+1 concatenation or adding of multiple strings in one operation while increasing argc by just 1. When the counters are used afterwards, arg strings can end up as env strings and vice versa (but not both the same time).


Security impact:

Until now, none found.

* The mixup of args and env strings does not matter, even with suid-binares, since it would have been possible to call the binary with other args/envp anyway, so mixup does not open new windows.

* Concatenation does not allow to exceed MAX_ARG_SIZE, since binfmt_elf will recheck them again, and race is not possible there, so fusioned argv/env strs will cause syscall termination.

* It seems, that there is no way to cause a memory leak, since all the args are put on new program stack and stack handling is correct, so pages are freed anyway.

* binfmt_script will remove argzero, which might remove more than that. In worst case, this will also remove bprm->exec data and overwrite it with user-supplied 0-byte-free data. The existence of 0-term bprm->exec string also protects against a user/kernel address mixup by going from 0xbffffffff to 0xc0000000 address on x86 with 3/1G split.

* bprm->exec is passed as auxv to elf binary, but is not used in SUID-binary library loading (seems that use of this attribute was removed 2008 from libc)

* The binfmt_misc and aout handler was not evaluated so far.
Comment 1 me 2011-07-12 14:55:31 UTC
Sorry imprecise: POC for timerace is available, exploitation not very complicated using CLONE_VM, but POC failed to trigger any OOPSes or lead to privilege escalation.
Comment 2 me 2011-07-15 00:28:36 UTC
Here is the POC:

* Two processes in same memory space, one doing exec, one changing arg data:

http://www.halfdog.net/Security/2011/KernelExecveArgvCopyTimerace/ExecArgAllTimerace.c

* Tool to detect when race was successful:

http://www.halfdog.net/Security/2011/KernelExecveArgvCopyTimerace/ArgAnomalyDetect.c

* Call it via test script to show arg0-removal:

http://www.halfdog.net/Security/2011/KernelExecveArgvCopyTimerace/TestScript.sh
Comment 3 xerofoify 2014-06-25 16:01:01 UTC
Please test this bug against a newer kernel to see if it's fixed.
Thanks Nick