aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Kuznetsov <alexey@openvz.org>2007-05-08 03:31:57 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:15:15 -0400
commitb140f25108a8b11aa4903014814988549838b324 (patch)
tree466b0c1a8056a2307c8219d1dfc5c059c043f07d
parentce0be1273d1473a5a7b57bf0b4995b40c22d6b54 (diff)
Invalid return value of execve() resulting in oopses
When elf loader fails to map executable (due to memory shortage or because binary is malformed), it can return 0. Normally, this is invisible because process is killed with SIGKILL and it never returns to user space. But if exec() is called from kernel thread (hotplug, whatever) consequences are more interesting and vary depending on architecture. i386. Nothing especially interesting, execve() just returns with "success" :-) x86_64. Fake zero frame is used on way to caller, RSP/RIP are loaded with zeros, ergo... double fault. ia64. Similar to i386, but r32...r95 are corrupted. Sometimes it oopses due to return to zero PC, sometimes it sees NaT in rXX and oopses due to NaT consumption. Signed-off-by: Alexey Kuznetsov <alexey@openvz.org> Signed-off-by: Kirill Korotaev <dev@openvz.org> Signed-off-by: Pavel Emelianov <xemul@openvz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/binfmt_elf.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 67d9b3148c06..fa8ea33ab0be 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -871,6 +871,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
871 elf_prot, elf_flags); 871 elf_prot, elf_flags);
872 if (BAD_ADDR(error)) { 872 if (BAD_ADDR(error)) {
873 send_sig(SIGKILL, current, 0); 873 send_sig(SIGKILL, current, 0);
874 retval = IS_ERR((void *)error) ?
875 PTR_ERR((void*)error) : -EINVAL;
874 goto out_free_dentry; 876 goto out_free_dentry;
875 } 877 }
876 878
@@ -900,6 +902,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
900 TASK_SIZE - elf_ppnt->p_memsz < k) { 902 TASK_SIZE - elf_ppnt->p_memsz < k) {
901 /* set_brk can never work. Avoid overflows. */ 903 /* set_brk can never work. Avoid overflows. */
902 send_sig(SIGKILL, current, 0); 904 send_sig(SIGKILL, current, 0);
905 retval = -EINVAL;
903 goto out_free_dentry; 906 goto out_free_dentry;
904 } 907 }
905 908