]> git.baikalelectronics.ru Git - kernel.git/commit
exec: do not leave bprm->interp on stack
authorKees Cook <keescook@chromium.org>
Thu, 20 Dec 2012 23:05:16 +0000 (15:05 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 21 Dec 2012 01:40:19 +0000 (17:40 -0800)
commitd43cd07634c43d4ce7c267d2b1b8d4216c069e07
tree78d1e5fc82a057c62699734602c8e5f7ca86b7a2
parent5b53406b221edf83d5c18adbab4b3eba2499dd00
exec: do not leave bprm->interp on stack

If a series of scripts are executed, each triggering module loading via
unprintable bytes in the script header, kernel stack contents can leak
into the command line.

Normally execution of binfmt_script and binfmt_misc happens recursively.
However, when modules are enabled, and unprintable bytes exist in the
bprm->buf, execution will restart after attempting to load matching
binfmt modules.  Unfortunately, the logic in binfmt_script and
binfmt_misc does not expect to get restarted.  They leave bprm->interp
pointing to their local stack.  This means on restart bprm->interp is
left pointing into unused stack memory which can then be copied into the
userspace argv areas.

After additional study, it seems that both recursion and restart remains
the desirable way to handle exec with scripts, misc, and modules.  As
such, we need to protect the changes to interp.

This changes the logic to require allocation for any changes to the
bprm->interp.  To avoid adding a new kmalloc to every exec, the default
value is left as-is.  Only when passing through binfmt_script or
binfmt_misc does an allocation take place.

For a proof of concept, see DoTest.sh from:

   http://www.halfdog.net/Security/2012/LinuxKernelBinfmtScriptStackDataDisclosure/

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: halfdog <me@halfdog.net>
Cc: P J P <ppandit@redhat.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/binfmt_misc.c
fs/binfmt_script.c
fs/exec.c
include/linux/binfmts.h