diff options
author | Roland McGrath <roland@redhat.com> | 2008-02-26 13:00:18 -0800 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-02-29 18:55:39 +0100 |
commit | 3d00daf44654dc75629caf42816ac4e293658724 (patch) | |
tree | 82775510cc3975ef28e800b6d0ea4032cbf86b79 | |
parent | c0f4133b8f70769bc8dda977feb9a29109d6ccca (diff) |
x86: tls prevent_tail_call
Fix a kernel bug (vmware boot problem) reported by Tomasz Grobelny,
which occurs with certain .config variants and gccs.
The x86 TLS cleanup in commit efd1ca52d04d2f6df337a3332cee56cd60e6d4c4
made the sys_set_thread_area and sys_get_thread_area functions ripe for
tail call optimization. If the compiler chooses to use it for them, it
can clobber the user trap frame because these are asmlinkage functions.
Reported-by: Tomasz Grobelny <tomasz@grobelny.oswiecenia.net>
Signed-off-by: Roland McGrath <roland@redhat.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r-- | arch/x86/kernel/tls.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index 6dfd4e76661a..022bcaa3b42e 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -91,7 +91,9 @@ int do_set_thread_area(struct task_struct *p, int idx, asmlinkage int sys_set_thread_area(struct user_desc __user *u_info) { - return do_set_thread_area(current, -1, u_info, 1); + int ret = do_set_thread_area(current, -1, u_info, 1); + prevent_tail_call(ret); + return ret; } @@ -139,7 +141,9 @@ int do_get_thread_area(struct task_struct *p, int idx, asmlinkage int sys_get_thread_area(struct user_desc __user *u_info) { - return do_get_thread_area(current, -1, u_info); + int ret = do_get_thread_area(current, -1, u_info); + prevent_tail_call(ret); + return ret; } int regset_tls_active(struct task_struct *target, |