diff options
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
| -rw-r--r-- | arch/x86/kernel/ptrace.c | 36 | 
1 files changed, 26 insertions, 10 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 45892dc4b72..f65e5b521db 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -608,6 +608,9 @@ static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data)  	unsigned len, type;  	struct perf_event *bp; +	if (ptrace_get_breakpoints(tsk) < 0) +		return -ESRCH; +  	data &= ~DR_CONTROL_RESERVED;  	old_dr7 = ptrace_get_dr7(thread->ptrace_bps);  restore: @@ -655,6 +658,9 @@ restore:  		}  		goto restore;  	} + +	ptrace_put_breakpoints(tsk); +  	return ((orig_ret < 0) ? orig_ret : rc);  } @@ -668,10 +674,17 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n)  	if (n < HBP_NUM) {  		struct perf_event *bp; + +		if (ptrace_get_breakpoints(tsk) < 0) +			return -ESRCH; +  		bp = thread->ptrace_bps[n];  		if (!bp) -			return 0; -		val = bp->hw.info.address; +			val = 0; +		else +			val = bp->hw.info.address; + +		ptrace_put_breakpoints(tsk);  	} else if (n == 6) {  		val = thread->debugreg6;  	 } else if (n == 7) { @@ -686,6 +699,10 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,  	struct perf_event *bp;  	struct thread_struct *t = &tsk->thread;  	struct perf_event_attr attr; +	int err = 0; + +	if (ptrace_get_breakpoints(tsk) < 0) +		return -ESRCH;  	if (!t->ptrace_bps[nr]) {  		ptrace_breakpoint_init(&attr); @@ -709,24 +726,23 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr,  		 * writing for the user. And anyway this is the previous  		 * behaviour.  		 */ -		if (IS_ERR(bp)) -			return PTR_ERR(bp); +		if (IS_ERR(bp)) { +			err = PTR_ERR(bp); +			goto put; +		}  		t->ptrace_bps[nr] = bp;  	} else { -		int err; -  		bp = t->ptrace_bps[nr];  		attr = bp->attr;  		attr.bp_addr = addr;  		err = modify_user_hw_breakpoint(bp, &attr); -		if (err) -			return err;  	} - -	return 0; +put: +	ptrace_put_breakpoints(tsk); +	return err;  }  /*  |