/[packages]/updates/2/kernel-rt/current/SOURCES/stable-exec-do-not-leave-bprm-interp-on-stack.patch
ViewVC logotype

Contents of /updates/2/kernel-rt/current/SOURCES/stable-exec-do-not-leave-bprm-interp-on-stack.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 338988 - (show annotations) (download)
Sat Jan 5 03:13:56 2013 UTC (11 years, 9 months ago) by tmb
File size: 4046 byte(s)
- fix xfs module failing to init/load properly (P253, P254, #7375)
- fix kernel stack disclosure in binfmt_script load_script() (P254)
  (CVE-2012-4530)


1 From b66c5984017533316fd1951770302649baf1aa33 Mon Sep 17 00:00:00 2001
2 From: Kees Cook <keescook@chromium.org>
3 Date: Thu, 20 Dec 2012 15:05:16 -0800
4 Subject: exec: do not leave bprm->interp on stack
5
6 From: Kees Cook <keescook@chromium.org>
7
8 commit b66c5984017533316fd1951770302649baf1aa33 upstream.
9
10 If a series of scripts are executed, each triggering module loading via
11 unprintable bytes in the script header, kernel stack contents can leak
12 into the command line.
13
14 Normally execution of binfmt_script and binfmt_misc happens recursively.
15 However, when modules are enabled, and unprintable bytes exist in the
16 bprm->buf, execution will restart after attempting to load matching
17 binfmt modules. Unfortunately, the logic in binfmt_script and
18 binfmt_misc does not expect to get restarted. They leave bprm->interp
19 pointing to their local stack. This means on restart bprm->interp is
20 left pointing into unused stack memory which can then be copied into the
21 userspace argv areas.
22
23 After additional study, it seems that both recursion and restart remains
24 the desirable way to handle exec with scripts, misc, and modules. As
25 such, we need to protect the changes to interp.
26
27 This changes the logic to require allocation for any changes to the
28 bprm->interp. To avoid adding a new kmalloc to every exec, the default
29 value is left as-is. Only when passing through binfmt_script or
30 binfmt_misc does an allocation take place.
31
32 For a proof of concept, see DoTest.sh from:
33
34 http://www.halfdog.net/Security/2012/LinuxKernelBinfmtScriptStackDataDisclosure/
35
36 Signed-off-by: Kees Cook <keescook@chromium.org>
37 Cc: halfdog <me@halfdog.net>
38 Cc: P J P <ppandit@redhat.com>
39 Cc: Alexander Viro <viro@zeniv.linux.org.uk>
40 Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
41 Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
42 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
43
44 ---
45 fs/binfmt_misc.c | 5 ++++-
46 fs/binfmt_script.c | 4 +++-
47 fs/exec.c | 15 +++++++++++++++
48 include/linux/binfmts.h | 1 +
49 4 files changed, 23 insertions(+), 2 deletions(-)
50
51 --- a/fs/binfmt_misc.c
52 +++ b/fs/binfmt_misc.c
53 @@ -176,7 +176,10 @@ static int load_misc_binary(struct linux
54 goto _error;
55 bprm->argc ++;
56
57 - bprm->interp = iname; /* for binfmt_script */
58 + /* Update interp in case binfmt_script needs it. */
59 + retval = bprm_change_interp(iname, bprm);
60 + if (retval < 0)
61 + goto _error;
62
63 interp_file = open_exec (iname);
64 retval = PTR_ERR (interp_file);
65 --- a/fs/binfmt_script.c
66 +++ b/fs/binfmt_script.c
67 @@ -82,7 +82,9 @@ static int load_script(struct linux_binp
68 retval = copy_strings_kernel(1, &i_name, bprm);
69 if (retval) return retval;
70 bprm->argc++;
71 - bprm->interp = interp;
72 + retval = bprm_change_interp(interp, bprm);
73 + if (retval < 0)
74 + return retval;
75
76 /*
77 * OK, now restart the process with the interpreter's dentry.
78 --- a/fs/exec.c
79 +++ b/fs/exec.c
80 @@ -1206,9 +1206,24 @@ void free_bprm(struct linux_binprm *bprm
81 mutex_unlock(&current->signal->cred_guard_mutex);
82 abort_creds(bprm->cred);
83 }
84 + /* If a binfmt changed the interp, free it. */
85 + if (bprm->interp != bprm->filename)
86 + kfree(bprm->interp);
87 kfree(bprm);
88 }
89
90 +int bprm_change_interp(char *interp, struct linux_binprm *bprm)
91 +{
92 + /* If a binfmt changed the interp, free it first. */
93 + if (bprm->interp != bprm->filename)
94 + kfree(bprm->interp);
95 + bprm->interp = kstrdup(interp, GFP_KERNEL);
96 + if (!bprm->interp)
97 + return -ENOMEM;
98 + return 0;
99 +}
100 +EXPORT_SYMBOL(bprm_change_interp);
101 +
102 /*
103 * install the new credentials for this executable
104 */
105 --- a/include/linux/binfmts.h
106 +++ b/include/linux/binfmts.h
107 @@ -128,6 +128,7 @@ extern int setup_arg_pages(struct linux_
108 unsigned long stack_top,
109 int executable_stack);
110 extern int bprm_mm_init(struct linux_binprm *bprm);
111 +extern int bprm_change_interp(char *interp, struct linux_binprm *bprm);
112 extern int copy_strings_kernel(int argc, const char *const *argv,
113 struct linux_binprm *bprm);
114 extern int prepare_bprm_creds(struct linux_binprm *bprm);

  ViewVC Help
Powered by ViewVC 1.1.30