aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill A. Shutemov <kirill@shutemov.name>2008-10-16 01:02:39 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-10-16 14:21:38 -0400
commitbf2a9a39639b8b51377905397a5005f444e9a892 (patch)
tree1919ad1abea804ce4cb1e7e8b1ac44b5b9a8f110
parent53112488bebe25c0f5f8a002470046c0fe9a6c61 (diff)
Allow recursion in binfmt_script and binfmt_misc
binfmt_script and binfmt_misc disallow recursion to avoid stack overflow using sh_bang and misc_bang. It causes problem in some cases: $ echo '#!/bin/ls' > /tmp/t0 $ echo '#!/tmp/t0' > /tmp/t1 $ echo '#!/tmp/t1' > /tmp/t2 $ chmod +x /tmp/t* $ /tmp/t2 zsh: exec format error: /tmp/t2 Similar problem with binfmt_misc. This patch introduces field 'recursion_depth' into struct linux_binprm to track recursion level in binfmt_misc and binfmt_script. If recursion level more then BINPRM_MAX_RECURSION it generates -ENOEXEC. [akpm@linux-foundation.org: make linux_binprm.recursion_depth a uint] Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> Cc: Pavel Emelyanov <xemul@openvz.org> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/binfmt_em86.c2
-rw-r--r--fs/binfmt_misc.c4
-rw-r--r--fs/binfmt_script.c5
-rw-r--r--include/linux/binfmts.h2
4 files changed, 8 insertions, 5 deletions
diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c
index f9c88d0c8ced..32fb00b52cd0 100644
--- a/fs/binfmt_em86.c
+++ b/fs/binfmt_em86.c
@@ -43,7 +43,7 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs)
43 return -ENOEXEC; 43 return -ENOEXEC;
44 } 44 }
45 45
46 bprm->sh_bang = 1; /* Well, the bang-shell is implicit... */ 46 bprm->recursion_depth++; /* Well, the bang-shell is implicit... */
47 allow_write_access(bprm->file); 47 allow_write_access(bprm->file);
48 fput(bprm->file); 48 fput(bprm->file);
49 bprm->file = NULL; 49 bprm->file = NULL;
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 8d7e88e02e0f..f2744ab4e5b3 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -117,7 +117,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
117 goto _ret; 117 goto _ret;
118 118
119 retval = -ENOEXEC; 119 retval = -ENOEXEC;
120 if (bprm->misc_bang) 120 if (bprm->recursion_depth > BINPRM_MAX_RECURSION)
121 goto _ret; 121 goto _ret;
122 122
123 /* to keep locking time low, we copy the interpreter string */ 123 /* to keep locking time low, we copy the interpreter string */
@@ -197,7 +197,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs)
197 if (retval < 0) 197 if (retval < 0)
198 goto _error; 198 goto _error;
199 199
200 bprm->misc_bang = 1; 200 bprm->recursion_depth++;
201 201
202 retval = search_binary_handler (bprm, regs); 202 retval = search_binary_handler (bprm, regs);
203 if (retval < 0) 203 if (retval < 0)
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c
index 9e3963f7ebf1..08343505e184 100644
--- a/fs/binfmt_script.c
+++ b/fs/binfmt_script.c
@@ -22,14 +22,15 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs)
22 char interp[BINPRM_BUF_SIZE]; 22 char interp[BINPRM_BUF_SIZE];
23 int retval; 23 int retval;
24 24
25 if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || (bprm->sh_bang)) 25 if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') ||
26 (bprm->recursion_depth > BINPRM_MAX_RECURSION))
26 return -ENOEXEC; 27 return -ENOEXEC;
27 /* 28 /*
28 * This section does the #! interpretation. 29 * This section does the #! interpretation.
29 * Sorta complicated, but hopefully it will work. -TYT 30 * Sorta complicated, but hopefully it will work. -TYT
30 */ 31 */
31 32
32 bprm->sh_bang = 1; 33 bprm->recursion_depth++;
33 allow_write_access(bprm->file); 34 allow_write_access(bprm->file);
34 fput(bprm->file); 35 fput(bprm->file);
35 bprm->file = NULL; 36 bprm->file = NULL;
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 54980a3c7602..7394b5b349ff 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -39,6 +39,7 @@ struct linux_binprm{
39#ifdef __alpha__ 39#ifdef __alpha__
40 unsigned int taso:1; 40 unsigned int taso:1;
41#endif 41#endif
42 unsigned int recursion_depth;
42 struct file * file; 43 struct file * file;
43 int e_uid, e_gid; 44 int e_uid, e_gid;
44 kernel_cap_t cap_post_exec_permitted; 45 kernel_cap_t cap_post_exec_permitted;
@@ -61,6 +62,7 @@ struct linux_binprm{
61#define BINPRM_FLAGS_EXECFD_BIT 1 62#define BINPRM_FLAGS_EXECFD_BIT 1
62#define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT) 63#define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT)
63 64
65#define BINPRM_MAX_RECURSION 4
64 66
65/* 67/*
66 * This structure defines the functions that are used to load the binary formats that 68 * This structure defines the functions that are used to load the binary formats that