diff options
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
-rw-r--r-- | arch/x86/kernel/ptrace.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 0a5df5f82fb9..5a4c23d89892 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -810,12 +810,16 @@ static void ptrace_bts_untrace(struct task_struct *child) | |||
810 | 810 | ||
811 | static void ptrace_bts_detach(struct task_struct *child) | 811 | static void ptrace_bts_detach(struct task_struct *child) |
812 | { | 812 | { |
813 | if (unlikely(child->bts)) { | 813 | /* |
814 | ds_release_bts(child->bts); | 814 | * Ptrace_detach() races with ptrace_untrace() in case |
815 | child->bts = NULL; | 815 | * the child dies and is reaped by another thread. |
816 | 816 | * | |
817 | ptrace_bts_free_buffer(child); | 817 | * We only do the memory accounting at this point and |
818 | } | 818 | * leave the buffer deallocation and the bts tracer |
819 | * release to ptrace_bts_untrace() which will be called | ||
820 | * later on with tasklist_lock held. | ||
821 | */ | ||
822 | release_locked_buffer(child->bts_buffer, child->bts_size); | ||
819 | } | 823 | } |
820 | #else | 824 | #else |
821 | static inline void ptrace_bts_fork(struct task_struct *tsk) {} | 825 | static inline void ptrace_bts_fork(struct task_struct *tsk) {} |