x86, fpu: misc fixes/cleanups, more to come
cover x86, fpu: misc fixes/cleanups, more to come
Peter, please consider this series for inclusion.
I added v2 tag to avoid the confusion but the patches are the same, except the new/offtopic but hopefully trivial 7/7.
2-6 were acked by Suresh (thanks!), the 1st patch still has no acks although iiuc Linus seems to agree with this change.
Oleg.
arch/x86/include/asm/fpu-internal.h | 2 +- arch/x86/kernel/process.c | 16 +++++++++------- arch/x86/kernel/process_32.c | 6 +----- arch/x86/kernel/process_64.c | 3 --- arch/x86/kernel/signal.c | 5 +++++ arch/x86/kernel/xsave.c | 7 ++++--- 6 files changed, 20 insertions(+), 19 deletions(-)
PATCH v2 1/7 x86, fpu: shift drop_init_fpu() from save_xstate_sig() to handle_signal()
save_xstate_sig()->drop_init_fpu() doesn't look right. setup_rt_frame() can fail after that, in this case the next setup_rt_frame() triggered by SIGSEGV won't save fpu simply because the old state was lost. This obviously mean that fpu won't be restored after sys_rt_sigreturn() from SIGSEGV handler.
Shift drop_init_fpu() into !failed branch in handle_signal().
Test-case (needs -O2):
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <pthread.h>
#include <assert.h>
volatile double D;
void test(double d)
{
int pid = getpid();
for (D = d; D == d; ) {
/* sys_tkill(pid, SIGHUP); asm to avoid save/reload
* fp regs around "C" call */
asm ("" : : "a"(200), "D"(pid), "S"(1));
asm ("syscall" : : : "ax");
}
printf("ERR!!\n");
}
void sigh(int sig)
{
}
char altstack[4096 * 10] __attribute__((aligned(4096)));
void *tfunc(void *arg)
{
for (;;) {
mprotect(altstack, sizeof(altstack), PROT_READ);
mprotect(altstack, sizeof(altstack), PROT_READ|PROT_WRITE);
}
}
int main(void)
{
stack_t st = {
.ss_sp = altstack,
.ss_size = sizeof(altstack),
.ss_flags = SS_ONSTACK,
};
struct sigaction sa = {
.sa_handler = sigh,
};
pthread_t pt;
sigaction(SIGSEGV, &sa, NULL);
sigaltstack(&st, NULL);
sa.sa_flags = SA_ONSTACK;
sigaction(SIGHUP, &sa, NULL);
pthread_create(&pt, NULL, tfunc, NULL);
test(123.456);
return 0;
}--- arch/x86/kernel/signal.c | 5 +++++ arch/x86/kernel/xsave.c | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-)
arch/x86/kernel/signal.c +5 -0
@@ -675,6 +675,11 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)* handler too. */ regs->flags &= ~(X86_EFLAGS_DF |X86_EFLAGS_RF |X86_EFLAGS_TF ); +/* +* Ensure the signal handler starts with the new fpu state. +*/ +if (used_math ()) +drop_init_fpu (current); }signal_setup_done (failed, ksig,test_thread_flag (TIF_SINGLESTEP )); }
arch/x86/kernel/xsave.c +0 -2
@@ -268,8 +268,6 @@ int save_xstate_sig(void __user *buf, void __user *buf_fx, int size)if (use_fxsr () &&save_xstate_epilog (buf_fx, ia32_fxstate))return -1 ; -drop_init_fpu (tsk);/* trigger finit */ -return 0 ; }
Signature · 1 line
1.5.5.1
tip-bot for Oleg Nesterov
merge bot[tip:x86/fpu] x86, fpu: shift drop_init_fpu() from save_xstate_sig() to handle_signal()
x86, fpu: shift drop_init_fpu() from save_xstate_sig() to handle_signal()
Commit-ID: 66463db4fc5605d51c7bb81d009d5bf30a783a2c Gitweb: http://git.kernel.org/tip/66463db4fc5605d51c7bb81d009d5bf30a783a2c Author: Oleg Nesterov <[email protected]> AuthorDate: Tue, 2 Sep 2014 19:57:13 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 2 Sep 2014 14:51:14 -0700
x86, fpu: shift drop_init_fpu() from save_xstate_sig() to handle_signal()
save_xstate_sig()->drop_init_fpu() doesn't look right. setup_rt_frame() can fail after that, in this case the next setup_rt_frame() triggered by SIGSEGV won't save fpu simply because the old state was lost. This obviously mean that fpu won't be restored after sys_rt_sigreturn() from SIGSEGV handler.
Shift drop_init_fpu() into !failed branch in handle_signal().
Test-case (needs -O2):
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/mman.h>
#include <pthread.h>
#include <assert.h>
volatile double D;
void test(double d)
{
int pid = getpid();
for (D = d; D == d; ) {
/* sys_tkill(pid, SIGHUP); asm to avoid save/reload
* fp regs around "C" call */
asm ("" : : "a"(200), "D"(pid), "S"(1));
asm ("syscall" : : : "ax");
}
printf("ERR!!\n");
}
void sigh(int sig)
{
}
char altstack[4096 * 10] __attribute__((aligned(4096)));
void *tfunc(void *arg)
{
for (;;) {
mprotect(altstack, sizeof(altstack), PROT_READ);
mprotect(altstack, sizeof(altstack), PROT_READ|PROT_WRITE);
}
}
int main(void)
{
stack_t st = {
.ss_sp = altstack,
.ss_size = sizeof(altstack),
.ss_flags = SS_ONSTACK,
};
struct sigaction sa = {
.sa_handler = sigh,
};
pthread_t pt;
sigaction(SIGSEGV, &sa, NULL);
sigaltstack(&st, NULL);
sa.sa_flags = SA_ONSTACK;
sigaction(SIGHUP, &sa, NULL);
pthread_create(&pt, NULL, tfunc, NULL);
test(123.456);
return 0;
}--- arch/x86/kernel/signal.c | 5 +++++ arch/x86/kernel/xsave.c | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-)
arch/x86/kernel/signal.c +5 -0
@@ -675,6 +675,11 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)* handler too. */ regs->flags &= ~(X86_EFLAGS_DF |X86_EFLAGS_RF |X86_EFLAGS_TF ); +/* +* Ensure the signal handler starts with the new fpu state. +*/ +if (used_math ()) +drop_init_fpu (current); }signal_setup_done (failed, ksig,test_thread_flag (TIF_SINGLESTEP )); }
arch/x86/kernel/xsave.c +0 -2
@@ -271,8 +271,6 @@ int save_xstate_sig(void __user *buf, void __user *buf_fx, int size)if (use_fxsr () &&save_xstate_epilog (buf_fx, ia32_fxstate))return -1 ; -drop_init_fpu (tsk);/* trigger finit */ -return 0 ; }
PATCH v2 2/7 x86, fpu: __restore_xstate_sig()->math_state_restore() needs preempt_disable()
In reply to Oleg NesterovAdd preempt_disable() + preempt_enable() around math_state_restore() in __restore_xstate_sig(). Otherwise __switch_to() after __thread_fpu_begin() can overwrite fpu->state we are going to restore.
--- arch/x86/kernel/xsave.c | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-)
arch/x86/kernel/xsave.c +4 -1
@@ -397,8 +397,11 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)set_used_math (); } -if (use_eager_fpu ()) +if (use_eager_fpu ()) { +preempt_disable ();math_state_restore (); +preempt_enable (); + }return err; }else {
Signature · 1 line
1.5.5.1
tip-bot for Oleg Nesterov
merge bot[tip:x86/fpu] x86, fpu: __restore_xstate_sig()-> math_state_restore() needs preempt_disable()
x86, fpu: __restore_xstate_sig()->math_state_restore() needs preempt_disable()
Commit-ID: df24fb859a4e200d9324e2974229fbb7adf00aef Gitweb: http://git.kernel.org/tip/df24fb859a4e200d9324e2974229fbb7adf00aef Author: Oleg Nesterov <[email protected]> AuthorDate: Tue, 2 Sep 2014 19:57:17 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 2 Sep 2014 14:51:15 -0700
x86, fpu: __restore_xstate_sig()->math_state_restore() needs preempt_disable()
Add preempt_disable() + preempt_enable() around math_state_restore() in __restore_xstate_sig(). Otherwise __switch_to() after __thread_fpu_begin() can overwrite fpu->state we are going to restore.
--- arch/x86/kernel/xsave.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/x86/kernel/xsave.c +4 -1
@@ -400,8 +400,11 @@ int __restore_xstate_sig(void __user *buf, void __user *buf_fx, int size)set_used_math (); } -if (use_eager_fpu ()) +if (use_eager_fpu ()) { +preempt_disable ();math_state_restore (); +preempt_enable (); + }return err; }else {
PATCH v2 3/7 x86, fpu: change __thread_fpu_begin() to use use_eager_fpu()
In reply to Oleg Nesterov__thread_fpu_begin() checks X86_FEATURE_EAGER_FPU by hand, we have a helper for that.
--- arch/x86/include/asm/fpu-internal.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
arch/x86/include/asm/fpu-internal.h +1 -1
@@ -344,7 +344,7 @@ static inline void __thread_fpu_end(struct task_struct *tsk)static inline void __thread_fpu_begin (struct task_struct *tsk) { -if (!static_cpu_has_safe (X86_FEATURE_EAGER_FPU )) +if (!use_eager_fpu ())clts ();__thread_set_has_fpu (tsk); }
Signature · 1 line
1.5.5.1
tip-bot for Oleg Nesterov
merge bot[tip:x86/fpu] x86, fpu: Change __thread_fpu_begin() to use use_eager_fpu()
x86, fpu: Change __thread_fpu_begin() to use use_eager_fpu()
Commit-ID: 31d963389f67165402aa447a8e8ce5ffb9188b3d Gitweb: http://git.kernel.org/tip/31d963389f67165402aa447a8e8ce5ffb9188b3d Author: Oleg Nesterov <[email protected]> AuthorDate: Tue, 2 Sep 2014 19:57:20 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 2 Sep 2014 14:51:15 -0700
x86, fpu: Change __thread_fpu_begin() to use use_eager_fpu()
__thread_fpu_begin() checks X86_FEATURE_EAGER_FPU by hand, we have a helper for that.
--- arch/x86/include/asm/fpu-internal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/fpu-internal.h +1 -1
@@ -344,7 +344,7 @@ static inline void __thread_fpu_end(struct task_struct *tsk)static inline void __thread_fpu_begin (struct task_struct *tsk) { -if (!static_cpu_has_safe (X86_FEATURE_EAGER_FPU )) +if (!use_eager_fpu ())clts ();__thread_set_has_fpu (tsk); }
PATCH v2 4/7 x86, fpu: copy_process: avoid fpu_alloc/copy if !used_math()
In reply to Oleg Nesterovarch_dup_task_struct() copies thread.fpu if fpu_allocated(), this looks suboptimal and misleading. Say, a forking process could use FPU only once in a signal handler but now tsk_used_math(src) == F, in this case the child gets a copy of fpu->state for no reason. The child won't use the saved registers anyway even if it starts to use FPU, this can only avoid fpu_alloc() in do_device_not_available().
Change this code to check tsk_used_math(current) instead. We still need to clear fpu->has_fpu/state, we could do this memset(0) under fpu_allocated() check but I think this doesn't make sense. See also the next change.
use_eager_fpu() assumes that fpu_allocated() is always true, but a forking task (and thus its child) must always have PF_USED_MATH set, otherwise the child can either use FPU without used_math() (note that switch_fpu_prepare() doesn't do stts() in this case), or it will be killed by do_device_not_available()->BUG_ON(use_eager_fpu).
--- arch/x86/kernel/process.c | 13 ++++++------- 1 files changed, 6 insertions(+), 7 deletions(-)
arch/x86/kernel/process.c +6 -7
@@ -64,14 +64,13 @@ EXPORT_SYMBOL_GPL(task_xstate_cachep);*/ int arch_dup_task_struct (struct task_struct *dst,struct task_struct *src) { -int ret; - *dst = *src; -if (fpu_allocated (&src->thread.fpu)) { -memset (&dst->thread.fpu,0 ,sizeof (dst->thread.fpu)); - ret =fpu_alloc (&dst->thread.fpu); -if (ret) -return ret; + +memset (&dst->thread.fpu,0 ,sizeof (dst->thread.fpu)); +if (tsk_used_math (src)) { +int err =fpu_alloc (&dst->thread.fpu); +if (err) +return err;fpu_copy (dst, src); }return 0 ;
Signature · 1 line
1.5.5.1
tip-bot for Oleg Nesterov
merge bot[tip:x86/fpu] x86, fpu: copy_process: Avoid fpu_alloc/ copy if !used_math()
x86, fpu: copy_process: Avoid fpu_alloc/copy if !used_math()
Commit-ID: f1853505d9ca1c3ea27c29cf83c24661531c527b Gitweb: http://git.kernel.org/tip/f1853505d9ca1c3ea27c29cf83c24661531c527b Author: Oleg Nesterov <[email protected]> AuthorDate: Tue, 2 Sep 2014 19:57:23 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 2 Sep 2014 14:51:16 -0700
x86, fpu: copy_process: Avoid fpu_alloc/copy if !used_math()
arch_dup_task_struct() copies thread.fpu if fpu_allocated(), this looks suboptimal and misleading. Say, a forking process could use FPU only once in a signal handler but now tsk_used_math(src) == F, in this case the child gets a copy of fpu->state for no reason. The child won't use the saved registers anyway even if it starts to use FPU, this can only avoid fpu_alloc() in do_device_not_available().
Change this code to check tsk_used_math(current) instead. We still need to clear fpu->has_fpu/state, we could do this memset(0) under fpu_allocated() check but I think this doesn't make sense. See also the next change.
use_eager_fpu() assumes that fpu_allocated() is always true, but a forking task (and thus its child) must always have PF_USED_MATH set, otherwise the child can either use FPU without used_math() (note that switch_fpu_prepare() doesn't do stts() in this case), or it will be killed by do_device_not_available()->BUG_ON(use_eager_fpu).
--- arch/x86/kernel/process.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
arch/x86/kernel/process.c +6 -7
@@ -64,14 +64,13 @@ EXPORT_SYMBOL_GPL(task_xstate_cachep);*/ int arch_dup_task_struct (struct task_struct *dst,struct task_struct *src) { -int ret; - *dst = *src; -if (fpu_allocated (&src->thread.fpu)) { -memset (&dst->thread.fpu,0 ,sizeof (dst->thread.fpu)); - ret =fpu_alloc (&dst->thread.fpu); -if (ret) -return ret; + +memset (&dst->thread.fpu,0 ,sizeof (dst->thread.fpu)); +if (tsk_used_math (src)) { +int err =fpu_alloc (&dst->thread.fpu); +if (err) +return err;fpu_copy (dst, src); }return 0 ;
PATCH v2 5/7 x86, fpu: copy_process: sanitize fpu->last_cpu initialization
In reply to Oleg NesterovCosmetic, but imho memset(&dst->thread.fpu, 0) is not good simply because it hides the (important) usage of ->has_fpu/etc from grep. Change this code to initialize the members explicitly.
And note that ->last_cpu = 0 looks simply wrong, this can confuse fpu_lazy_restore() if per_cpu(fpu_owner_task, 0) has already exited and copy_process() re-allocated the same task_struct. Fortunately this is not actually possible because child->fpu_counter == 0 and thus fpu_lazy_restore() will not be called, but still this is not clean/robust.
--- arch/x86/kernel/process.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-)
arch/x86/kernel/process.c +3 -1
@@ -66,7 +66,9 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { *dst = *src; -memset (&dst->thread.fpu,0 ,sizeof (dst->thread.fpu)); + dst->thread.fpu.has_fpu =0 ; + dst->thread.fpu.last_cpu = ~0 ; + dst->thread.fpu.state =NULL ;if (tsk_used_math (src)) {int err =fpu_alloc (&dst->thread.fpu);if (err)
Signature · 1 line
1.5.5.1
tip-bot for Oleg Nesterov
merge bot[tip:x86/fpu] x86, fpu: copy_process: Sanitize fpu-> last_cpu initialization
x86, fpu: copy_process: Sanitize fpu->last_cpu initialization
Commit-ID: 5e23fee23ea10730c752edce1777e6b7e727290f Gitweb: http://git.kernel.org/tip/5e23fee23ea10730c752edce1777e6b7e727290f Author: Oleg Nesterov <[email protected]> AuthorDate: Tue, 2 Sep 2014 19:57:27 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 2 Sep 2014 14:51:16 -0700
x86, fpu: copy_process: Sanitize fpu->last_cpu initialization
Cosmetic, but imho memset(&dst->thread.fpu, 0) is not good simply because it hides the (important) usage of ->has_fpu/etc from grep. Change this code to initialize the members explicitly.
And note that ->last_cpu = 0 looks simply wrong, this can confuse fpu_lazy_restore() if per_cpu(fpu_owner_task, 0) has already exited and copy_process() re-allocated the same task_struct. Fortunately this is not actually possible because child->fpu_counter == 0 and thus fpu_lazy_restore() will not be called, but still this is not clean/robust.
--- arch/x86/kernel/process.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kernel/process.c +3 -1
@@ -66,7 +66,9 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { *dst = *src; -memset (&dst->thread.fpu,0 ,sizeof (dst->thread.fpu)); + dst->thread.fpu.has_fpu =0 ; + dst->thread.fpu.last_cpu = ~0 ; + dst->thread.fpu.state =NULL ;if (tsk_used_math (src)) {int err =fpu_alloc (&dst->thread.fpu);if (err)
PATCH v2 6/7 x86, fpu: shift "fpu_counter = 0" from copy_thread() to arch_dup_task_struct()
In reply to Oleg NesterovCosmetic, but I think thread.fpu_counter should be initialized in arch_dup_task_struct() too, along with other "fpu" variables. And probably it make sense to turn it into thread.fpu->counter.
--- arch/x86/kernel/process.c | 1 + arch/x86/kernel/process_32.c | 2 -- arch/x86/kernel/process_64.c | 1 - 3 files changed, 1 insertions(+), 3 deletions(-)
arch/x86/kernel/process.c +1 -0
@@ -66,6 +66,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { *dst = *src; + dst->thread.fpu_counter =0 ; dst->thread.fpu.has_fpu =0 ; dst->thread.fpu.last_cpu = ~0 ; dst->thread.fpu.state =NULL ;
arch/x86/kernel/process_32.c +0 -2
@@ -152,7 +152,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, childregs->orig_ax =-1 ; childregs->cs = __KERNEL_CS |get_kernel_rpl (); childregs->flags =X86_EFLAGS_IF |X86_EFLAGS_FIXED ; - p->thread.fpu_counter =0 ; p->thread.io_bitmap_ptr =NULL ;memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps));return 0 ;
@@ -165,7 +164,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, p->thread.ip = (unsigned long ) ret_from_fork;task_user_gs (p) =get_user_gs (current_pt_regs ()); - p->thread.fpu_counter =0 ; p->thread.io_bitmap_ptr =NULL ; tsk = current; err = -ENOMEM ;
arch/x86/kernel/process_64.c +0 -1
@@ -163,7 +163,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, p->thread.sp = (unsigned long ) childregs; p->thread.usersp = me->thread.usersp;set_tsk_thread_flag (p,TIF_FORK ); - p->thread.fpu_counter =0 ; p->thread.io_bitmap_ptr =NULL ;savesegment (gs, p->thread.gsindex);
Signature · 1 line
1.5.5.1
tip-bot for Oleg Nesterov
merge bot[tip:x86/fpu] x86, fpu: Shift "fpu_counter = 0" from copy_thread( ) to arch_dup_task_struct()
x86, fpu: Shift "fpu_counter = 0" from copy_thread() to arch_dup_task_struct()
Commit-ID: dc56c0f9b870fba7a4eef2bb463db6881284152b Gitweb: http://git.kernel.org/tip/dc56c0f9b870fba7a4eef2bb463db6881284152b Author: Oleg Nesterov <[email protected]> AuthorDate: Tue, 2 Sep 2014 19:57:30 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 2 Sep 2014 14:51:16 -0700
x86, fpu: Shift "fpu_counter = 0" from copy_thread() to arch_dup_task_struct()
Cosmetic, but I think thread.fpu_counter should be initialized in arch_dup_task_struct() too, along with other "fpu" variables. And probably it make sense to turn it into thread.fpu->counter.
--- arch/x86/kernel/process.c | 1 + arch/x86/kernel/process_32.c | 2 -- arch/x86/kernel/process_64.c | 1 - 3 files changed, 1 insertion(+), 3 deletions(-)
arch/x86/kernel/process.c +1 -0
@@ -66,6 +66,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) { *dst = *src; + dst->thread.fpu_counter =0 ; dst->thread.fpu.has_fpu =0 ; dst->thread.fpu.last_cpu = ~0 ; dst->thread.fpu.state =NULL ;
arch/x86/kernel/process_32.c +0 -2
@@ -152,7 +152,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, childregs->orig_ax =-1 ; childregs->cs = __KERNEL_CS |get_kernel_rpl (); childregs->flags =X86_EFLAGS_IF |X86_EFLAGS_FIXED ; - p->thread.fpu_counter =0 ; p->thread.io_bitmap_ptr =NULL ;memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps));return 0 ;
@@ -165,7 +164,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, p->thread.ip = (unsigned long ) ret_from_fork;task_user_gs (p) =get_user_gs (current_pt_regs ()); - p->thread.fpu_counter =0 ; p->thread.io_bitmap_ptr =NULL ; tsk = current; err = -ENOMEM ;
arch/x86/kernel/process_64.c +0 -1
@@ -163,7 +163,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, p->thread.sp = (unsigned long ) childregs; p->thread.usersp = me->thread.usersp;set_tsk_thread_flag (p,TIF_FORK ); - p->thread.fpu_counter =0 ; p->thread.io_bitmap_ptr =NULL ;savesegment (gs, p->thread.gsindex);
PATCH v2 7/7 x86: copy_thread: don't nullify ->ptrace_bps twice
In reply to Oleg NesterovBoth 32bit and 64bit versions of copy_thread() do memset(ptrace_bps) twice for no reason, kill the 2nd memset().
--- arch/x86/kernel/process_32.c | 4 +--- arch/x86/kernel/process_64.c | 2 -- 2 files changed, 1 insertions(+), 5 deletions(-)
arch/x86/kernel/process_32.c +1 -3
@@ -138,6 +138,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, p->thread.sp = (unsigned long ) childregs; p->thread.sp0 = (unsigned long ) (childregs+1 ); +memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps));if (unlikely (p->flags &PF_KTHREAD )) {/* kernel thread */
@@ -153,7 +154,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, childregs->cs = __KERNEL_CS |get_kernel_rpl (); childregs->flags =X86_EFLAGS_IF |X86_EFLAGS_FIXED ; p->thread.io_bitmap_ptr =NULL ; -memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps));return 0 ; } *childregs = *current_pt_regs ();
@@ -168,8 +168,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, tsk = current; err = -ENOMEM ; -memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps)); -if (unlikely (test_tsk_thread_flag (tsk,TIF_IO_BITMAP ))) { p->thread.io_bitmap_ptr =kmemdup (tsk->thread.io_bitmap_ptr,IO_BITMAP_BYTES ,GFP_KERNEL );
arch/x86/kernel/process_64.c +0 -2
@@ -192,8 +192,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, childregs->sp = sp; err = -ENOMEM ; -memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps)); -if (unlikely (test_tsk_thread_flag (me,TIF_IO_BITMAP ))) { p->thread.io_bitmap_ptr =kmemdup (me->thread.io_bitmap_ptr,IO_BITMAP_BYTES ,GFP_KERNEL );
Signature · 1 line
1.5.5.1
tip-bot for Oleg Nesterov
merge bot[tip:x86/fpu] x86: copy_thread: Don't nullify ->ptrace_bps twice
x86: copy_thread: Don't nullify ->ptrace_bps twice
Commit-ID: 6f46b3aef0031c08a7b439d63013dad2aeb093b2 Gitweb: http://git.kernel.org/tip/6f46b3aef0031c08a7b439d63013dad2aeb093b2 Author: Oleg Nesterov <[email protected]> AuthorDate: Tue, 2 Sep 2014 19:57:33 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Tue, 2 Sep 2014 14:51:17 -0700
x86: copy_thread: Don't nullify ->ptrace_bps twice
Both 32bit and 64bit versions of copy_thread() do memset(ptrace_bps) twice for no reason, kill the 2nd memset().
--- arch/x86/kernel/process_32.c | 4 +--- arch/x86/kernel/process_64.c | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-)
arch/x86/kernel/process_32.c +1 -3
@@ -138,6 +138,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, p->thread.sp = (unsigned long ) childregs; p->thread.sp0 = (unsigned long ) (childregs+1 ); +memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps));if (unlikely (p->flags &PF_KTHREAD )) {/* kernel thread */
@@ -153,7 +154,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, childregs->cs = __KERNEL_CS |get_kernel_rpl (); childregs->flags =X86_EFLAGS_IF |X86_EFLAGS_FIXED ; p->thread.io_bitmap_ptr =NULL ; -memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps));return 0 ; } *childregs = *current_pt_regs ();
@@ -168,8 +168,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, tsk = current; err = -ENOMEM ; -memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps)); -if (unlikely (test_tsk_thread_flag (tsk,TIF_IO_BITMAP ))) { p->thread.io_bitmap_ptr =kmemdup (tsk->thread.io_bitmap_ptr,IO_BITMAP_BYTES ,GFP_KERNEL );
arch/x86/kernel/process_64.c +0 -2
@@ -192,8 +192,6 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, childregs->sp = sp; err = -ENOMEM ; -memset (p->thread.ptrace_bps,0 ,sizeof (p->thread.ptrace_bps)); -if (unlikely (test_tsk_thread_flag (me,TIF_IO_BITMAP ))) { p->thread.io_bitmap_ptr =kmemdup (me->thread.io_bitmap_ptr,IO_BITMAP_BYTES ,GFP_KERNEL );