diff options
Diffstat (limited to 'arch/arm64/kernel/ptrace.c')
| -rw-r--r-- | arch/arm64/kernel/ptrace.c | 23 | 
1 files changed, 15 insertions, 8 deletions
| diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index e0c81da60f76..a22161ccf447 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -327,13 +327,13 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,  				     struct arch_hw_breakpoint_ctrl ctrl,  				     struct perf_event_attr *attr)  { -	int err, len, type, disabled = !ctrl.enabled; +	int err, len, type, offset, disabled = !ctrl.enabled;  	attr->disabled = disabled;  	if (disabled)  		return 0; -	err = arch_bp_generic_fields(ctrl, &len, &type); +	err = arch_bp_generic_fields(ctrl, &len, &type, &offset);  	if (err)  		return err; @@ -352,6 +352,7 @@ static int ptrace_hbp_fill_attr_ctrl(unsigned int note_type,  	attr->bp_len	= len;  	attr->bp_type	= type; +	attr->bp_addr	+= offset;  	return 0;  } @@ -404,7 +405,7 @@ static int ptrace_hbp_get_addr(unsigned int note_type,  	if (IS_ERR(bp))  		return PTR_ERR(bp); -	*addr = bp ? bp->attr.bp_addr : 0; +	*addr = bp ? counter_arch_bp(bp)->address : 0;  	return 0;  } @@ -550,6 +551,8 @@ static int hw_break_set(struct task_struct *target,  	/* (address, ctrl) registers */  	limit = regset->n * regset->size;  	while (count && offset < limit) { +		if (count < PTRACE_HBP_ADDR_SZ) +			return -EINVAL;  		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &addr,  					 offset, offset + PTRACE_HBP_ADDR_SZ);  		if (ret) @@ -559,6 +562,8 @@ static int hw_break_set(struct task_struct *target,  			return ret;  		offset += PTRACE_HBP_ADDR_SZ; +		if (!count) +			break;  		ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl,  					 offset, offset + PTRACE_HBP_CTRL_SZ);  		if (ret) @@ -595,7 +600,7 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,  		   const void *kbuf, const void __user *ubuf)  {  	int ret; -	struct user_pt_regs newregs; +	struct user_pt_regs newregs = task_pt_regs(target)->user_regs;  	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newregs, 0, -1);  	if (ret) @@ -625,7 +630,8 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset,  		   const void *kbuf, const void __user *ubuf)  {  	int ret; -	struct user_fpsimd_state newstate; +	struct user_fpsimd_state newstate = +		target->thread.fpsimd_state.user_fpsimd;  	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &newstate, 0, -1);  	if (ret) @@ -649,7 +655,7 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset,  		   const void *kbuf, const void __user *ubuf)  {  	int ret; -	unsigned long tls; +	unsigned long tls = target->thread.tp_value;  	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);  	if (ret) @@ -675,7 +681,8 @@ static int system_call_set(struct task_struct *target,  			   unsigned int pos, unsigned int count,  			   const void *kbuf, const void __user *ubuf)  { -	int syscallno, ret; +	int syscallno = task_pt_regs(target)->syscallno; +	int ret;  	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &syscallno, 0, -1);  	if (ret) @@ -947,7 +954,7 @@ static int compat_tls_set(struct task_struct *target,  			  const void __user *ubuf)  {  	int ret; -	compat_ulong_t tls; +	compat_ulong_t tls = target->thread.tp_value;  	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &tls, 0, -1);  	if (ret) |