diff mbox series

[4/4] linux-user: Handle rt_sigaction correctly for SPARC

Message ID 1509993206-26637-5-git-send-email-peter.maydell@linaro.org
State Accepted
Headers show
Series linux-user: fix various SIGSEGV delivery bugs | expand

Commit Message

Peter Maydell Nov. 6, 2017, 6:33 p.m. UTC
SPARC is like Alpha in its handling of the rt_sigaction syscall:
it takes an extra parameter 'restorer' which needs to be copied
into the sa_restorer field of the sigaction struct. The order
of the arguments differs slightly between SPARC and Alpha but
the implementation is otherwise the same. (Compare the
rt_sigaction() functions in arch/sparc/kernel/sys_sparc_64.c
and arch/alpha/kernel/signal.c.)

Note that this change is somewhat moot until SPARC acquires
support for actually delivering RT signals.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

---
 linux-user/syscall.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

-- 
2.7.4

Comments

Laurent Vivier Nov. 7, 2017, 2:11 p.m. UTC | #1
Le 06/11/2017 à 19:33, Peter Maydell a écrit :
> SPARC is like Alpha in its handling of the rt_sigaction syscall:

> it takes an extra parameter 'restorer' which needs to be copied

> into the sa_restorer field of the sigaction struct. The order

> of the arguments differs slightly between SPARC and Alpha but

> the implementation is otherwise the same. (Compare the

> rt_sigaction() functions in arch/sparc/kernel/sys_sparc_64.c

> and arch/alpha/kernel/signal.c.)

> 

> Note that this change is somewhat moot until SPARC acquires

> support for actually delivering RT signals.

> 

> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

> ---

>  linux-user/syscall.c | 27 +++++++++++++++++++++++----

>  1 file changed, 23 insertions(+), 4 deletions(-)

> 

> diff --git a/linux-user/syscall.c b/linux-user/syscall.c

> index d4497de..8beab51 100644

> --- a/linux-user/syscall.c

> +++ b/linux-user/syscall.c

> @@ -8556,8 +8556,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,

>      case TARGET_NR_rt_sigaction:

>          {

>  #if defined(TARGET_ALPHA)

> -            struct target_sigaction act, oact, *pact = 0;

> +            /* For Alpha and SPARC this is a 5 argument syscall, with

> +             * a 'restorer' parameter which must be copied into the

> +             * sa_restorer field of the sigaction struct.

> +             * For Alpha that 'restorer' is arg5; for SPARC it is arg4,

> +             * and arg5 is the sigsetsize.

> +             * Alpha also has a separate rt_sigaction struct that it uses

> +             * here; SPARC uses the usual sigaction struct.

> +             */

>              struct target_rt_sigaction *rt_act;

> +            struct target_sigaction act, oact, *pact = 0;

>  

>              if (arg4 != sizeof(target_sigset_t)) {

>                  ret = -TARGET_EINVAL;

> @@ -8583,18 +8591,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,

>                  unlock_user_struct(rt_act, arg3, 1);

>              }

>  #else

> +#ifdef TARGET_SPARC

> +            target_ulong restorer = arg4;

> +            target_ulong sigsetsize = arg5;

> +#else

> +            target_ulong sigsetsize = arg4;

> +#endif

>              struct target_sigaction *act;

>              struct target_sigaction *oact;

>  

> -            if (arg4 != sizeof(target_sigset_t)) {

> +            if (sigsetsize != sizeof(target_sigset_t)) {

>                  ret = -TARGET_EINVAL;

>                  break;

>              }

>              if (arg2) {

> -                if (!lock_user_struct(VERIFY_READ, act, arg2, 1))

> +                if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {

>                      goto efault;

> -            } else

> +                }

> +#ifdef TARGET_SPARC

> +                act->sa_restorer = restorer;

> +#endif

> +            } else {

>                  act = NULL;

> +            }

>              if (arg3) {

>                  if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {

>                      ret = -TARGET_EFAULT;

> 


Reviewed-by: Laurent Vivier <laurent@vivier.eu>
Philippe Mathieu-Daudé Nov. 7, 2017, 3:44 p.m. UTC | #2
Hi Peter,

On 11/06/2017 03:33 PM, Peter Maydell wrote:
> SPARC is like Alpha in its handling of the rt_sigaction syscall:

> it takes an extra parameter 'restorer' which needs to be copied

> into the sa_restorer field of the sigaction struct. The order

> of the arguments differs slightly between SPARC and Alpha but

> the implementation is otherwise the same. (Compare the

> rt_sigaction() functions in arch/sparc/kernel/sys_sparc_64.c

> and arch/alpha/kernel/signal.c.)

> 

> Note that this change is somewhat moot until SPARC acquires

> support for actually delivering RT signals.

> 

> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

> ---

>  linux-user/syscall.c | 27 +++++++++++++++++++++++----

>  1 file changed, 23 insertions(+), 4 deletions(-)

> 

> diff --git a/linux-user/syscall.c b/linux-user/syscall.c

> index d4497de..8beab51 100644

> --- a/linux-user/syscall.c

> +++ b/linux-user/syscall.c

> @@ -8556,8 +8556,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,

>      case TARGET_NR_rt_sigaction:

>          {


> -            struct target_sigaction act, oact, *pact = 0;

> +            /* For Alpha and SPARC this is a 5 argument syscall, with

> +             * a 'restorer' parameter which must be copied into the

> +             * sa_restorer field of the sigaction struct.

> +             * For Alpha that 'restorer' is arg5; for SPARC it is arg4,

> +             * and arg5 is the sigsetsize.

> +             * Alpha also has a separate rt_sigaction struct that it uses

> +             * here; SPARC uses the usual sigaction struct.

> +             */


I find it easier to read moving the #if after the comment.
Since using restorer for sparc improve readability we can use it for
alpha as well (code is a bit more consistent):

  #if defined(TARGET_ALPHA)
               target_ulong restorer = arg5;

>              struct target_rt_sigaction *rt_act;

> +            struct target_sigaction act, oact, *pact = 0;

>  

>              if (arg4 != sizeof(target_sigset_t)) {

>                  ret = -TARGET_EINVAL;


...
                   act.sa_restorer = restorer;

Whichever way:
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>


> @@ -8583,18 +8591,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,

>                  unlock_user_struct(rt_act, arg3, 1);

>              }

>  #else

> +#ifdef TARGET_SPARC

> +            target_ulong restorer = arg4;

> +            target_ulong sigsetsize = arg5;

> +#else

> +            target_ulong sigsetsize = arg4;

> +#endif

>              struct target_sigaction *act;

>              struct target_sigaction *oact;

>  

> -            if (arg4 != sizeof(target_sigset_t)) {

> +            if (sigsetsize != sizeof(target_sigset_t)) {

>                  ret = -TARGET_EINVAL;

>                  break;

>              }

>              if (arg2) {

> -                if (!lock_user_struct(VERIFY_READ, act, arg2, 1))

> +                if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {

>                      goto efault;

> -            } else

> +                }

> +#ifdef TARGET_SPARC

> +                act->sa_restorer = restorer;

> +#endif

> +            } else {

>                  act = NULL;

> +            }

>              if (arg3) {

>                  if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {

>                      ret = -TARGET_EFAULT;

>
diff mbox series

Patch

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d4497de..8beab51 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8556,8 +8556,16 @@  abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
     case TARGET_NR_rt_sigaction:
         {
 #if defined(TARGET_ALPHA)
-            struct target_sigaction act, oact, *pact = 0;
+            /* For Alpha and SPARC this is a 5 argument syscall, with
+             * a 'restorer' parameter which must be copied into the
+             * sa_restorer field of the sigaction struct.
+             * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
+             * and arg5 is the sigsetsize.
+             * Alpha also has a separate rt_sigaction struct that it uses
+             * here; SPARC uses the usual sigaction struct.
+             */
             struct target_rt_sigaction *rt_act;
+            struct target_sigaction act, oact, *pact = 0;
 
             if (arg4 != sizeof(target_sigset_t)) {
                 ret = -TARGET_EINVAL;
@@ -8583,18 +8591,29 @@  abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 unlock_user_struct(rt_act, arg3, 1);
             }
 #else
+#ifdef TARGET_SPARC
+            target_ulong restorer = arg4;
+            target_ulong sigsetsize = arg5;
+#else
+            target_ulong sigsetsize = arg4;
+#endif
             struct target_sigaction *act;
             struct target_sigaction *oact;
 
-            if (arg4 != sizeof(target_sigset_t)) {
+            if (sigsetsize != sizeof(target_sigset_t)) {
                 ret = -TARGET_EINVAL;
                 break;
             }
             if (arg2) {
-                if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
+                if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {
                     goto efault;
-            } else
+                }
+#ifdef TARGET_SPARC
+                act->sa_restorer = restorer;
+#endif
+            } else {
                 act = NULL;
+            }
             if (arg3) {
                 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
                     ret = -TARGET_EFAULT;