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.c45
1 files changed, 34 insertions, 11 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 6ad2bb607650..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 }
@@ -784,6 +799,9 @@ static void ptrace_bts_untrace(struct task_struct *child)
784 ds_release_bts(child->bts); 799 ds_release_bts(child->bts);
785 child->bts = NULL; 800 child->bts = NULL;
786 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. */
787 kfree(child->bts_buffer); 805 kfree(child->bts_buffer);
788 child->bts_buffer = NULL; 806 child->bts_buffer = NULL;
789 child->bts_size = 0; 807 child->bts_size = 0;
@@ -792,7 +810,12 @@ static void ptrace_bts_untrace(struct task_struct *child)
792 810
793static void ptrace_bts_detach(struct task_struct *child) 811static void ptrace_bts_detach(struct task_struct *child)
794{ 812{
795 ptrace_bts_untrace(child); 813 if (unlikely(child->bts)) {
814 ds_release_bts(child->bts);
815 child->bts = NULL;
816
817 ptrace_bts_free_buffer(child);
818 }
796} 819}
797#else 820#else
798static inline void ptrace_bts_fork(struct task_struct *tsk) {} 821static inline void ptrace_bts_fork(struct task_struct *tsk) {}