Patchwork powerpc: fixing ptrace_get_reg to return an error

login
register
mail settings
Submitter Alexey Kardashevskiy
Date Feb. 15, 2013, 3:44 a.m.
Message ID <1360899863-17181-1-git-send-email-aik@ozlabs.ru>
Download mbox | patch
Permalink /patch/220620/
State Accepted
Commit ee4a3916614829914830bc4371358f4d4a63c4d9
Delegated to: Michael Ellerman
Headers show

Comments

Alexey Kardashevskiy - Feb. 15, 2013, 3:44 a.m.
Currently ptrace_get_reg returns error as a value
what make impossible to tell whether it is a correct value or error code.

The patch adds a parameter which points to the real return data and
returns an error code.

As get_user_msr() never fails and it is used in multiple places so it has not
been changed by this patch.

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 arch/powerpc/include/asm/ptrace.h |    3 ++-
 arch/powerpc/kernel/ptrace.c      |   29 ++++++++++++++++++-----------
 arch/powerpc/kernel/ptrace32.c    |   15 ++++++++++++---
 3 files changed, 32 insertions(+), 15 deletions(-)
Michael Neuling - April 10, 2013, 5 a.m.
Alexey Kardashevskiy <aik@ozlabs.ru> wrote:

> Currently ptrace_get_reg returns error as a value
> what make impossible to tell whether it is a correct value or error code.
> 
> The patch adds a parameter which points to the real return data and
> returns an error code.
> 
> As get_user_msr() never fails and it is used in multiple places so it has not
> been changed by this patch.
> 
> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>

FWIW:
Acked-by: Michael Neuling <mikey@neuling.org>


> ---
>  arch/powerpc/include/asm/ptrace.h |    3 ++-
>  arch/powerpc/kernel/ptrace.c      |   29 ++++++++++++++++++-----------
>  arch/powerpc/kernel/ptrace32.c    |   15 ++++++++++++---
>  3 files changed, 32 insertions(+), 15 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
> index 5f99568..becc08e 100644
> --- a/arch/powerpc/include/asm/ptrace.h
> +++ b/arch/powerpc/include/asm/ptrace.h
> @@ -92,7 +92,8 @@ static inline long regs_return_value(struct pt_regs *regs)
>  	} while(0)
>  
>  struct task_struct;
> -extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
> +extern int ptrace_get_reg(struct task_struct *task, int regno,
> +			  unsigned long *data);
>  extern int ptrace_put_reg(struct task_struct *task, int regno,
>  			  unsigned long data);
>  
> diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
> index 245c1b6..d5ff7ea 100644
> --- a/arch/powerpc/kernel/ptrace.c
> +++ b/arch/powerpc/kernel/ptrace.c
> @@ -180,9 +180,10 @@ static int set_user_msr(struct task_struct *task, unsigned long msr)
>  }
>  
>  #ifdef CONFIG_PPC64
> -static unsigned long get_user_dscr(struct task_struct *task)
> +static int get_user_dscr(struct task_struct *task, unsigned long *data)
>  {
> -	return task->thread.dscr;
> +	*data = task->thread.dscr;
> +	return 0;
>  }
>  
>  static int set_user_dscr(struct task_struct *task, unsigned long dscr)
> @@ -192,7 +193,7 @@ static int set_user_dscr(struct task_struct *task, unsigned long dscr)
>  	return 0;
>  }
>  #else
> -static unsigned long get_user_dscr(struct task_struct *task)
> +static int get_user_dscr(struct task_struct *task, unsigned long *data)
>  {
>  	return -EIO;
>  }
> @@ -216,19 +217,23 @@ static int set_user_trap(struct task_struct *task, unsigned long trap)
>  /*
>   * Get contents of register REGNO in task TASK.
>   */
> -unsigned long ptrace_get_reg(struct task_struct *task, int regno)
> +int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data)
>  {
> -	if (task->thread.regs == NULL)
> +	if ((task->thread.regs == NULL) || !data)
>  		return -EIO;
>  
> -	if (regno == PT_MSR)
> -		return get_user_msr(task);
> +	if (regno == PT_MSR) {
> +		*data = get_user_msr(task);
> +		return 0;
> +	}
>  
>  	if (regno == PT_DSCR)
> -		return get_user_dscr(task);
> +		return get_user_dscr(task, data);
>  
> -	if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
> -		return ((unsigned long *)task->thread.regs)[regno];
> +	if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
> +		*data = ((unsigned long *)task->thread.regs)[regno];
> +		return 0;
> +	}
>  
>  	return -EIO;
>  }
> @@ -1559,7 +1564,9 @@ long arch_ptrace(struct task_struct *child, long request,
>  
>  		CHECK_FULL_REGS(child->thread.regs);
>  		if (index < PT_FPR0) {
> -			tmp = ptrace_get_reg(child, (int) index);
> +			ret = ptrace_get_reg(child, (int) index, &tmp);
> +			if (ret)
> +				break;
>  		} else {
>  			unsigned int fpidx = index - PT_FPR0;
>  
> diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
> index c0244e7..f51599e 100644
> --- a/arch/powerpc/kernel/ptrace32.c
> +++ b/arch/powerpc/kernel/ptrace32.c
> @@ -95,7 +95,9 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
>  
>  		CHECK_FULL_REGS(child->thread.regs);
>  		if (index < PT_FPR0) {
> -			tmp = ptrace_get_reg(child, index);
> +			ret = ptrace_get_reg(child, index, &tmp);
> +			if (ret)
> +				break;
>  		} else {
>  			flush_fp_to_thread(child);
>  			/*
> @@ -148,7 +150,11 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
>  			tmp = ((u64 *)child->thread.fpr)
>  				[FPRINDEX_3264(numReg)];
>  		} else { /* register within PT_REGS struct */
> -			tmp = ptrace_get_reg(child, numReg);
> +			unsigned long tmp2;
> +			ret = ptrace_get_reg(child, numReg, &tmp2);
> +			if (ret)
> +				break;
> +			tmp = tmp2;
>  		} 
>  		reg32bits = ((u32*)&tmp)[part];
>  		ret = put_user(reg32bits, (u32 __user *)data);
> @@ -232,7 +238,10 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
>  			break;
>  		CHECK_FULL_REGS(child->thread.regs);
>  		if (numReg < PT_FPR0) {
> -			unsigned long freg = ptrace_get_reg(child, numReg);
> +			unsigned long freg;
> +			ret = ptrace_get_reg(child, numReg, &freg);
> +			if (ret)
> +				break;
>  			if (index % 2)
>  				freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
>  			else
> -- 
> 1.7.10.4
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>

Patch

diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 5f99568..becc08e 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -92,7 +92,8 @@  static inline long regs_return_value(struct pt_regs *regs)
 	} while(0)
 
 struct task_struct;
-extern unsigned long ptrace_get_reg(struct task_struct *task, int regno);
+extern int ptrace_get_reg(struct task_struct *task, int regno,
+			  unsigned long *data);
 extern int ptrace_put_reg(struct task_struct *task, int regno,
 			  unsigned long data);
 
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c
index 245c1b6..d5ff7ea 100644
--- a/arch/powerpc/kernel/ptrace.c
+++ b/arch/powerpc/kernel/ptrace.c
@@ -180,9 +180,10 @@  static int set_user_msr(struct task_struct *task, unsigned long msr)
 }
 
 #ifdef CONFIG_PPC64
-static unsigned long get_user_dscr(struct task_struct *task)
+static int get_user_dscr(struct task_struct *task, unsigned long *data)
 {
-	return task->thread.dscr;
+	*data = task->thread.dscr;
+	return 0;
 }
 
 static int set_user_dscr(struct task_struct *task, unsigned long dscr)
@@ -192,7 +193,7 @@  static int set_user_dscr(struct task_struct *task, unsigned long dscr)
 	return 0;
 }
 #else
-static unsigned long get_user_dscr(struct task_struct *task)
+static int get_user_dscr(struct task_struct *task, unsigned long *data)
 {
 	return -EIO;
 }
@@ -216,19 +217,23 @@  static int set_user_trap(struct task_struct *task, unsigned long trap)
 /*
  * Get contents of register REGNO in task TASK.
  */
-unsigned long ptrace_get_reg(struct task_struct *task, int regno)
+int ptrace_get_reg(struct task_struct *task, int regno, unsigned long *data)
 {
-	if (task->thread.regs == NULL)
+	if ((task->thread.regs == NULL) || !data)
 		return -EIO;
 
-	if (regno == PT_MSR)
-		return get_user_msr(task);
+	if (regno == PT_MSR) {
+		*data = get_user_msr(task);
+		return 0;
+	}
 
 	if (regno == PT_DSCR)
-		return get_user_dscr(task);
+		return get_user_dscr(task, data);
 
-	if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long)))
-		return ((unsigned long *)task->thread.regs)[regno];
+	if (regno < (sizeof(struct pt_regs) / sizeof(unsigned long))) {
+		*data = ((unsigned long *)task->thread.regs)[regno];
+		return 0;
+	}
 
 	return -EIO;
 }
@@ -1559,7 +1564,9 @@  long arch_ptrace(struct task_struct *child, long request,
 
 		CHECK_FULL_REGS(child->thread.regs);
 		if (index < PT_FPR0) {
-			tmp = ptrace_get_reg(child, (int) index);
+			ret = ptrace_get_reg(child, (int) index, &tmp);
+			if (ret)
+				break;
 		} else {
 			unsigned int fpidx = index - PT_FPR0;
 
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c
index c0244e7..f51599e 100644
--- a/arch/powerpc/kernel/ptrace32.c
+++ b/arch/powerpc/kernel/ptrace32.c
@@ -95,7 +95,9 @@  long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
 		CHECK_FULL_REGS(child->thread.regs);
 		if (index < PT_FPR0) {
-			tmp = ptrace_get_reg(child, index);
+			ret = ptrace_get_reg(child, index, &tmp);
+			if (ret)
+				break;
 		} else {
 			flush_fp_to_thread(child);
 			/*
@@ -148,7 +150,11 @@  long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 			tmp = ((u64 *)child->thread.fpr)
 				[FPRINDEX_3264(numReg)];
 		} else { /* register within PT_REGS struct */
-			tmp = ptrace_get_reg(child, numReg);
+			unsigned long tmp2;
+			ret = ptrace_get_reg(child, numReg, &tmp2);
+			if (ret)
+				break;
+			tmp = tmp2;
 		} 
 		reg32bits = ((u32*)&tmp)[part];
 		ret = put_user(reg32bits, (u32 __user *)data);
@@ -232,7 +238,10 @@  long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 			break;
 		CHECK_FULL_REGS(child->thread.regs);
 		if (numReg < PT_FPR0) {
-			unsigned long freg = ptrace_get_reg(child, numReg);
+			unsigned long freg;
+			ret = ptrace_get_reg(child, numReg, &freg);
+			if (ret)
+				break;
 			if (index % 2)
 				freg = (freg & ~0xfffffffful) | (data & 0xfffffffful);
 			else