All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] linux-user: Fix indirect syscall handling for MIPS
@ 2011-08-04 22:16 An-Cheng Huang
  2011-08-04 22:43 ` Peter Maydell
  0 siblings, 1 reply; 6+ messages in thread
From: An-Cheng Huang @ 2011-08-04 22:16 UTC (permalink / raw)
  To: qemu-devel; +Cc: riku.voipio

I ran into the problem of indirect syscalls not working with mips-linux-user and found that the number of arguments for sys_syscall is 0 in the mips_syscall_args table, which means the "higher" arguments (5, 6, 7, and 8) are never obtained from the stack for the do_syscall() invocation for indirect syscalls. So the actual syscall will not get the correct argument(s) if it needs more than three.

The patch checks for indirect syscall and in such cases uses the actual syscall number to look up the number of arguments so that the actual arguments can be taken from the stack.

A simpler approach would be to just change the number of arguments for sys_syscall to 8 in the mips_syscall_args table so that for indirect syscalls the "higher" arguments are always taken from the stack with get_user_ual(). However, since there is a comment about "what to do if get_user() fails", I don't know if this may cause breakage when the arguments are not actually there? If someone can confirm that this is harmless, the simple approach is probably better? Thanks.

Signed-off-by: An-Cheng Huang <ancheng@ubnt.com>
---
 linux-user/main.c |   21 ++++++++++++++++++---
 1 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 6a8f4bd..1560c1c 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2068,27 +2068,42 @@ static int do_store_exclusive(CPUMIPSState *env)
 void cpu_loop(CPUMIPSState *env)
 {
     target_siginfo_t info;
     int trapnr, ret;
     unsigned int syscall_num;
+    unsigned int syscall_idx;
+    unsigned int real_syscall_idx; /* only for indirect syscall */
 
     for(;;) {
         cpu_exec_start(env);
         trapnr = cpu_mips_exec(env);
         cpu_exec_end(env);
         switch(trapnr) {
         case EXCP_SYSCALL:
-            syscall_num = env->active_tc.gpr[2] - 4000;
+            syscall_num = env->active_tc.gpr[2];
+            syscall_idx = syscall_num - 4000;
+            real_syscall_idx = env->active_tc.gpr[4] - 4000;
             env->active_tc.PC += 4;
-            if (syscall_num >= sizeof(mips_syscall_args)) {
+            if (syscall_idx >= sizeof(mips_syscall_args)
+                || (syscall_num == TARGET_NR_syscall
+                    && real_syscall_idx >= sizeof(mips_syscall_args))) {
+                /* invalid direct or indirect syscalls */
                 ret = -TARGET_ENOSYS;
             } else {
                 int nb_args;
                 abi_ulong sp_reg;
                 abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
 
-                nb_args = mips_syscall_args[syscall_num];
+                if (syscall_num == TARGET_NR_syscall) {
+                    /* indirect syscall, so need to look at the real
+                     * syscall to figure out nb_args. also, plus 1 is
+                     * needed to account for the indirect syscall itself.
+                     */
+                    nb_args = mips_syscall_args[real_syscall_idx] + 1;
+                } else {
+                    nb_args = mips_syscall_args[syscall_idx];
+                }
                 sp_reg = env->active_tc.gpr[29];
                 switch (nb_args) {
                 /* these arguments are taken from the stack */
                 /* FIXME - what to do if get_user() fails? */
                 case 8: get_user_ual(arg8, sp_reg + 28);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Fix indirect syscall handling for MIPS
  2011-08-04 22:16 [Qemu-devel] [PATCH] linux-user: Fix indirect syscall handling for MIPS An-Cheng Huang
@ 2011-08-04 22:43 ` Peter Maydell
  2011-08-05  0:05   ` An-Cheng Huang
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Maydell @ 2011-08-04 22:43 UTC (permalink / raw)
  To: An-Cheng Huang; +Cc: riku.voipio, qemu-devel

On 4 August 2011 23:16, An-Cheng Huang <ancheng@ubnt.com> wrote:
> I ran into the problem of indirect syscalls not working with
> mips-linux-user and found that the number of arguments for sys_syscall
> is 0 in the mips_syscall_args table, which means the "higher" arguments
> (5, 6, 7, and 8) are never obtained from the stack for the do_syscall()
> invocation for indirect syscalls. So the actual syscall will not get the
> correct argument(s) if it needs more than three.

Yes, I noticed this last time I was looking at this code.

> A simpler approach would be to just change the number of arguments for
> sys_syscall to 8 in the mips_syscall_args table so that for indirect
> syscalls the "higher" arguments are always taken from the stack with
> get_user_ual(). However, since there is a comment about "what to do
> if get_user() fails", I don't know if this may cause breakage when the
> arguments are not actually there? If someone can confirm that this is
> harmless, the simple approach is probably better? Thanks.

In fact the Linux kernel will always read all four arguments off the
stack for sys_syscall, regardless:
http://lxr.linux.no/#linux+v3.0/arch/mips/kernel/scall32-o32.S#L188

So setting sys_syscall to 8 is not just easier but actually the Right
Thing. The comment about get_user() is cut-n-paste from various other
places in the file where it applies just as much -- it is no more of
an issue for MIPS or for sys_syscall than for any other architecture
or syscall. [ie it is a bug, but not in practice a very serious one,
and you can ignore it for the purposes of fixing the bug you've found
here.]

Incidentally, you can find the answer to the "what if get_user fails"
question for MIPS here:
http://lxr.linux.no/#linux+v3.0/arch/mips/kernel/scall32-o32.S#L166
...we should set ret to -TARGET_EFAULT and skip the call to do_syscall.

-- PMM

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Fix indirect syscall handling for MIPS
  2011-08-04 22:43 ` Peter Maydell
@ 2011-08-05  0:05   ` An-Cheng Huang
  2011-08-05  9:27     ` Peter Maydell
  0 siblings, 1 reply; 6+ messages in thread
From: An-Cheng Huang @ 2011-08-05  0:05 UTC (permalink / raw)
  To: Peter Maydell; +Cc: riku.voipio, qemu-devel

On Thu, Aug 04, 2011 at 11:43:31PM +0100, Peter Maydell wrote:
> On 4 August 2011 23:16, An-Cheng Huang <ancheng@ubnt.com> wrote:
> > A simpler approach would be to just change the number of arguments for
> > sys_syscall to 8 in the mips_syscall_args table so that for indirect
> > syscalls the "higher" arguments are always taken from the stack with
> > get_user_ual(). However, since there is a comment about "what to do
> > if get_user() fails", I don't know if this may cause breakage when the
> > arguments are not actually there? If someone can confirm that this is
> > harmless, the simple approach is probably better? Thanks.
> 
> In fact the Linux kernel will always read all four arguments off the
> stack for sys_syscall, regardless:
> http://lxr.linux.no/#linux+v3.0/arch/mips/kernel/scall32-o32.S#L188
> 
> So setting sys_syscall to 8 is not just easier but actually the Right
> Thing. The comment about get_user() is cut-n-paste from various other
> places in the file where it applies just as much -- it is no more of
> an issue for MIPS or for sys_syscall than for any other architecture
> or syscall. [ie it is a bug, but not in practice a very serious one,
> and you can ignore it for the purposes of fixing the bug you've found
> here.]
> 
> Incidentally, you can find the answer to the "what if get_user fails"
> question for MIPS here:
> http://lxr.linux.no/#linux+v3.0/arch/mips/kernel/scall32-o32.S#L166
> ...we should set ret to -TARGET_EFAULT and skip the call to do_syscall.

Ok the following patch changes the number of arguments for sys_syscall to 8 in mips_syscall_args and also skips the do_syscall() call if any of the get_user() calls fails. Do you think combining these makes sense or should they be two separate patches? Thanks.

Signed-off-by: An-Cheng Huang <ancheng@ubnt.com>
---
 linux-user/main.c |   24 ++++++++++++++++++------
 1 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 6a8f4bd..701d96e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1669,7 +1669,7 @@ void cpu_loop(CPUPPCState *env)
 #define MIPS_SYS(name, args) args,
 
 static const uint8_t mips_syscall_args[] = {
-	MIPS_SYS(sys_syscall	, 0)	/* 4000 */
+	MIPS_SYS(sys_syscall	, 8)	/* 4000 */
 	MIPS_SYS(sys_exit	, 1)
 	MIPS_SYS(sys_fork	, 0)
 	MIPS_SYS(sys_read	, 3)
@@ -2090,11 +2090,22 @@ void cpu_loop(CPUMIPSState *env)
                 sp_reg = env->active_tc.gpr[29];
                 switch (nb_args) {
                 /* these arguments are taken from the stack */
-                /* FIXME - what to do if get_user() fails? */
-                case 8: get_user_ual(arg8, sp_reg + 28);
-                case 7: get_user_ual(arg7, sp_reg + 24);
-                case 6: get_user_ual(arg6, sp_reg + 20);
-                case 5: get_user_ual(arg5, sp_reg + 16);
+                case 8:
+                    if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
+                        goto done_syscall;
+                    }
+                case 7:
+                    if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
+                        goto done_syscall;
+                    }
+                case 6:
+                    if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
+                        goto done_syscall;
+                    }
+                case 5:
+                    if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
+                        goto done_syscall;
+                    }
                 default:
                     break;
                 }
@@ -2105,6 +2116,7 @@ void cpu_loop(CPUMIPSState *env)
                                  env->active_tc.gpr[7],
                                  arg5, arg6, arg7, arg8);
             }
+done_syscall:
             if (ret == -TARGET_QEMU_ESIGRETURN) {
                 /* Returning from a successful sigreturn syscall.
                    Avoid clobbering register state.  */

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH] linux-user: Fix indirect syscall handling for MIPS
  2011-08-05  0:05   ` An-Cheng Huang
@ 2011-08-05  9:27     ` Peter Maydell
  2011-08-05 17:54       ` [Qemu-devel] [PATCH 1/2] " An-Cheng Huang
  2011-08-05 17:57       ` [Qemu-devel] [PATCH 2/2] " An-Cheng Huang
  0 siblings, 2 replies; 6+ messages in thread
From: Peter Maydell @ 2011-08-05  9:27 UTC (permalink / raw)
  To: An-Cheng Huang; +Cc: riku.voipio, qemu-devel

On 5 August 2011 01:05, An-Cheng Huang <ancheng@ubnt.com> wrote:
> Ok the following patch changes the number of arguments for sys_syscall
> to 8 in mips_syscall_args and also skips the do_syscall() call if any
> of the get_user() calls fails. Do you think combining these makes sense
> or should they be two separate patches? Thanks.

The code in this patch looks good, but yes, I think they should
be two separate patches.

thanks
-- PMM

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 1/2] linux-user: Fix indirect syscall handling for MIPS
  2011-08-05  9:27     ` Peter Maydell
@ 2011-08-05 17:54       ` An-Cheng Huang
  2011-08-05 17:57       ` [Qemu-devel] [PATCH 2/2] " An-Cheng Huang
  1 sibling, 0 replies; 6+ messages in thread
From: An-Cheng Huang @ 2011-08-05 17:54 UTC (permalink / raw)
  To: Peter Maydell; +Cc: riku.voipio, qemu-devel

On Fri, Aug 05, 2011 at 10:27:21AM +0100, Peter Maydell wrote:
> On 5 August 2011 01:05, An-Cheng Huang <ancheng@ubnt.com> wrote:
> > Ok the following patch changes the number of arguments for sys_syscall
> > to 8 in mips_syscall_args and also skips the do_syscall() call if any
> > of the get_user() calls fails. Do you think combining these makes sense
> > or should they be two separate patches? Thanks.
> 
> The code in this patch looks good, but yes, I think they should
> be two separate patches.

Here's the first patch for the indirect syscall:

This patch changes the number of arguments for sys_syscall on MIPS to 8, which allows the arguments for the actual syscall to be handled correctly.

Signed-off-by: An-Cheng Huang <ancheng@ubnt.com>
---
 linux-user/main.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 6a8f4bd..9e67b24 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -1669,7 +1669,7 @@ void cpu_loop(CPUPPCState *env)
 #define MIPS_SYS(name, args) args,
 
 static const uint8_t mips_syscall_args[] = {
-	MIPS_SYS(sys_syscall	, 0)	/* 4000 */
+	MIPS_SYS(sys_syscall	, 8)	/* 4000 */
 	MIPS_SYS(sys_exit	, 1)
 	MIPS_SYS(sys_fork	, 0)
 	MIPS_SYS(sys_read	, 3)

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [PATCH 2/2] linux-user: Fix indirect syscall handling for MIPS
  2011-08-05  9:27     ` Peter Maydell
  2011-08-05 17:54       ` [Qemu-devel] [PATCH 1/2] " An-Cheng Huang
@ 2011-08-05 17:57       ` An-Cheng Huang
  1 sibling, 0 replies; 6+ messages in thread
From: An-Cheng Huang @ 2011-08-05 17:57 UTC (permalink / raw)
  To: Peter Maydell; +Cc: riku.voipio, qemu-devel

On Fri, Aug 05, 2011 at 10:27:21AM +0100, Peter Maydell wrote:
> On 5 August 2011 01:05, An-Cheng Huang <ancheng@ubnt.com> wrote:
> > Ok the following patch changes the number of arguments for sys_syscall
> > to 8 in mips_syscall_args and also skips the do_syscall() call if any
> > of the get_user() calls fails. Do you think combining these makes sense
> > or should they be two separate patches? Thanks.
> 
> The code in this patch looks good, but yes, I think they should
> be two separate patches.

And the second patch:

This patch verifies that MIPS syscall arguments are successfully taken from the stack before proceeding to do_syscall().

Signed-off-by: An-Cheng Huang <ancheng@ubnt.com>
---
 linux-user/main.c |   22 +++++++++++++++++-----
 1 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/linux-user/main.c b/linux-user/main.c
index 9e67b24..701d96e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2090,11 +2090,22 @@ void cpu_loop(CPUMIPSState *env)
                 sp_reg = env->active_tc.gpr[29];
                 switch (nb_args) {
                 /* these arguments are taken from the stack */
-                /* FIXME - what to do if get_user() fails? */
-                case 8: get_user_ual(arg8, sp_reg + 28);
-                case 7: get_user_ual(arg7, sp_reg + 24);
-                case 6: get_user_ual(arg6, sp_reg + 20);
-                case 5: get_user_ual(arg5, sp_reg + 16);
+                case 8:
+                    if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) {
+                        goto done_syscall;
+                    }
+                case 7:
+                    if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) {
+                        goto done_syscall;
+                    }
+                case 6:
+                    if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) {
+                        goto done_syscall;
+                    }
+                case 5:
+                    if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
+                        goto done_syscall;
+                    }
                 default:
                     break;
                 }
@@ -2105,6 +2116,7 @@ void cpu_loop(CPUMIPSState *env)
                                  env->active_tc.gpr[7],
                                  arg5, arg6, arg7, arg8);
             }
+done_syscall:
             if (ret == -TARGET_QEMU_ESIGRETURN) {
                 /* Returning from a successful sigreturn syscall.
                    Avoid clobbering register state.  */

^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2011-08-05 17:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-04 22:16 [Qemu-devel] [PATCH] linux-user: Fix indirect syscall handling for MIPS An-Cheng Huang
2011-08-04 22:43 ` Peter Maydell
2011-08-05  0:05   ` An-Cheng Huang
2011-08-05  9:27     ` Peter Maydell
2011-08-05 17:54       ` [Qemu-devel] [PATCH 1/2] " An-Cheng Huang
2011-08-05 17:57       ` [Qemu-devel] [PATCH 2/2] " An-Cheng Huang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.