aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/tls.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@redhat.com>2008-02-26 16:00:18 -0500
committerIngo Molnar <mingo@elte.hu>2008-02-29 12:55:39 -0500
commit3d00daf44654dc75629caf42816ac4e293658724 (patch)
tree82775510cc3975ef28e800b6d0ea4032cbf86b79 /arch/x86/kernel/tls.c
parentc0f4133b8f70769bc8dda977feb9a29109d6ccca (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>
Diffstat (limited to 'arch/x86/kernel/tls.c')
-rw-r--r--arch/x86/kernel/tls.c8
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,
91 91
92asmlinkage int sys_set_thread_area(struct user_desc __user *u_info) 92asmlinkage int sys_set_thread_area(struct user_desc __user *u_info)
93{ 93{
94 return do_set_thread_area(current, -1, u_info, 1); 94 int ret = do_set_thread_area(current, -1, u_info, 1);
95 prevent_tail_call(ret);
96 return ret;
95} 97}
96 98
97 99
@@ -139,7 +141,9 @@ int do_get_thread_area(struct task_struct *p, int idx,
139 141
140asmlinkage int sys_get_thread_area(struct user_desc __user *u_info) 142asmlinkage int sys_get_thread_area(struct user_desc __user *u_info)
141{ 143{
142 return do_get_thread_area(current, -1, u_info); 144 int ret = do_get_thread_area(current, -1, u_info);
145 prevent_tail_call(ret);
146 return ret;
143} 147}
144 148
145int regset_tls_active(struct task_struct *target, 149int regset_tls_active(struct task_struct *target,