aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
-rw-r--r--arch/x86/kernel/ptrace.c93
1 files changed, 73 insertions, 20 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 45e9855da2d2..0a5df5f82fb9 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -650,6 +650,24 @@ static int ptrace_bts_drain(struct task_struct *child,
650 return drained; 650 return drained;
651} 651}
652 652
653static int ptrace_bts_allocate_buffer(struct task_struct *child, size_t size)
654{
655 child->bts_buffer = alloc_locked_buffer(size);
656 if (!child->bts_buffer)
657 return -ENOMEM;
658
659 child->bts_size = size;
660
661 return 0;
662}
663
664static void ptrace_bts_free_buffer(struct task_struct *child)
665{
666 free_locked_buffer(child->bts_buffer, child->bts_size);
667 child->bts_buffer = NULL;
668 child->bts_size = 0;
669}
670
653static int ptrace_bts_config(struct task_struct *child, 671static int ptrace_bts_config(struct task_struct *child,
654 long cfg_size, 672 long cfg_size,
655 const struct ptrace_bts_config __user *ucfg) 673 const struct ptrace_bts_config __user *ucfg)
@@ -679,14 +697,13 @@ static int ptrace_bts_config(struct task_struct *child,
679 697
680 if ((cfg.flags & PTRACE_BTS_O_ALLOC) && 698 if ((cfg.flags & PTRACE_BTS_O_ALLOC) &&
681 (cfg.size != child->bts_size)) { 699 (cfg.size != child->bts_size)) {
682 kfree(child->bts_buffer); 700 int error;
683 701
684 child->bts_size = cfg.size; 702 ptrace_bts_free_buffer(child);
685 child->bts_buffer = kzalloc(cfg.size, GFP_KERNEL); 703
686 if (!child->bts_buffer) { 704 error = ptrace_bts_allocate_buffer(child, cfg.size);
687 child->bts_size = 0; 705 if (error < 0)
688 return -ENOMEM; 706 return error;
689 }
690 } 707 }
691 708
692 if (cfg.flags & PTRACE_BTS_O_TRACE) 709 if (cfg.flags & PTRACE_BTS_O_TRACE)
@@ -701,10 +718,8 @@ static int ptrace_bts_config(struct task_struct *child,
701 if (IS_ERR(child->bts)) { 718 if (IS_ERR(child->bts)) {
702 int error = PTR_ERR(child->bts); 719 int error = PTR_ERR(child->bts);
703 720
704 kfree(child->bts_buffer); 721 ptrace_bts_free_buffer(child);
705 child->bts = NULL; 722 child->bts = NULL;
706 child->bts_buffer = NULL;
707 child->bts_size = 0;
708 723
709 return error; 724 return error;
710 } 725 }
@@ -769,8 +784,55 @@ static int ptrace_bts_size(struct task_struct *child)
769 784
770 return (trace->ds.top - trace->ds.begin) / trace->ds.size; 785 return (trace->ds.top - trace->ds.begin) / trace->ds.size;
771} 786}
787
788static void ptrace_bts_fork(struct task_struct *tsk)
789{
790 tsk->bts = NULL;
791 tsk->bts_buffer = NULL;
792 tsk->bts_size = 0;
793 tsk->thread.bts_ovfl_signal = 0;
794}
795
796static void ptrace_bts_untrace(struct task_struct *child)
797{
798 if (unlikely(child->bts)) {
799 ds_release_bts(child->bts);
800 child->bts = NULL;
801
802 /* We cannot update total_vm and locked_vm since
803 child's mm is already gone. But we can reclaim the
804 memory. */
805 kfree(child->bts_buffer);
806 child->bts_buffer = NULL;
807 child->bts_size = 0;
808 }
809}
810
811static void ptrace_bts_detach(struct task_struct *child)
812{
813 if (unlikely(child->bts)) {
814 ds_release_bts(child->bts);
815 child->bts = NULL;
816
817 ptrace_bts_free_buffer(child);
818 }
819}
820#else
821static inline void ptrace_bts_fork(struct task_struct *tsk) {}
822static inline void ptrace_bts_detach(struct task_struct *child) {}
823static inline void ptrace_bts_untrace(struct task_struct *child) {}
772#endif /* CONFIG_X86_PTRACE_BTS */ 824#endif /* CONFIG_X86_PTRACE_BTS */
773 825
826void x86_ptrace_fork(struct task_struct *child, unsigned long clone_flags)
827{
828 ptrace_bts_fork(child);
829}
830
831void x86_ptrace_untrace(struct task_struct *child)
832{
833 ptrace_bts_untrace(child);
834}
835
774/* 836/*
775 * Called by kernel/ptrace.c when detaching.. 837 * Called by kernel/ptrace.c when detaching..
776 * 838 *
@@ -782,16 +844,7 @@ void ptrace_disable(struct task_struct *child)
782#ifdef TIF_SYSCALL_EMU 844#ifdef TIF_SYSCALL_EMU
783 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); 845 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
784#endif 846#endif
785#ifdef CONFIG_X86_PTRACE_BTS 847 ptrace_bts_detach(child);
786 if (child->bts) {
787 ds_release_bts(child->bts);
788 child->bts = NULL;
789
790 kfree(child->bts_buffer);
791 child->bts_buffer = NULL;
792 child->bts_size = 0;
793 }
794#endif /* CONFIG_X86_PTRACE_BTS */
795} 848}
796 849
797#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION 850#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION