All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling
@ 2017-05-15 14:59 Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 01/16] linux-user: add strace for getuid(), gettid(), getppid(), geteuid() Miloš Stojanović
                   ` (16 more replies)
  0 siblings, 17 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Change from v1 to v2:
tswapal_target_sigset() is no longer static since it was breaking the build.

This patch set deals with QEMU Linux user mode functionalities related to
signal handling. It is composed of four sections:

A. Extend strace support (patches 1-2, 8-9):

   Strace support is added for getuid(), gettid(), getppid(), geteuid(),
   tkill(), tgkill() and rt_sigqueueinfo(), along with support for printing
   the uinfo structure of rt_sigqueueinfo() of rt_tgsigqueueinfo() instead
   of a pointer to it. Additionally, some minor fixes of inconsistent spaces
   in the output of print_siginfo() are added.

B. Fix some signal handling issues (patches 3-5):

   Fix the ssetmask() system call by removing the invocation of
   sigorset() using the old and the new signal masks as arguments.
   Change the unlock_user() argument from arg1 to arg3 to match with
   lock_user(), since arg3 contains the pointer to the siginfo_t structure.
   Change the type of the first argument of rt_sigqueinfo()
   from int to pid_t in the syscall declaration.

C. Adding support for rt_tgsigqueueinfo() (patches 6-7):

   Add a new system call: rt_tgsigqueueinfo().

   This system call is similar to rt_sigqueueinfo(), but instead of
   sending the signal and data to the whole thread group with the ID
   equal to the argument tgid, it sends it to a single thread within
   that thread group. The ID of the thread is specified by the tid
   argument.

   The implementation is based on the rt_sigqueueinfo() in linux-user
   mode, where the tid is added as the second argument and the
   previous second and third argument become arguments three and four,
   respectively.

D. Add support for larger target signal range (RFC patches 10-16):

   Add target signal mask tracking and multiplexing of target signals out
   of the host range. The patches are marked as RFC because they introduce
   significant new functionalities regarding signal handling in QEMU.

   Currently, QEMU has a copy of the host signal and suspend masks and
   that is usually enough, since most of the time the signal mask of the
   target architecture is either the same length or narrower. If however
   the signal mask is wider, then part of it won't be tracked. The signals
   that are in the target range but out of the host range were treated like
   faulty signals and couldn't be used. This problem is solved by enabling
   the usage of one of the host signals as a multiplex for all the target
   signals that are out of range. In order to have the target signal masks
   available, tracking of target signal masks is implemented.

   The rt_sigqueueinfo()/rt_tgsigqueueinfo() system calls multiplex target
   signals by setting the si_errno value to the actual value of the signal
   and sending the signal to a predefined host signal number.
   The host_signal_handler() will pull out the multiplexed signals and set
   their signal number to the correct value. The si_errno field is used
   here but this implementation can be replaced with any other unused field
   in the uinfo structure. Using this implementation both rt_sigqueueinfo(),
   rt_tgsigqueueinfo(), as well as kill() (for pid > 0) and tgkill() can be
   emulated.

   The tkill() system call and kill() with the argument pid <= 0 couldn't
   be implemented simply using this method because it requires acquiring
   information about, and sending simultaneous signals to multiple threads
   or processes. These functionalities are out of the scope of
   rt_sigqueueinfo()/rt_tgsigqueueinfo().

Miloš Stojanović (16):
  linux-user: add strace for getuid(), gettid(), getppid(), geteuid()
  linux-user: add tkill(), tgkill() and rt_sigqueueinfo() strace
  linux-user: fix ssetmask() system call
  linux-user: fix mismatch of lock/unlock_user() invocations in
    rt_sigqueinfo() syscall
  linux-user: fix argument type declaration of rt_sigqueinfo() syscall
  linux-user: add support for rt_tgsigqueueinfo() system call
  linux-user: add rt_tgsigqueueinfo() strace
  linux-user: fix inconsistent spaces in print_siginfo() output
  linux-user: add strace support for uinfo structure of
    rt_sigqueueinfo() and rt_tgsigqueueinfo()
  [RFC] linux-user: add support for tracking the target signal mask
  [RFC] linux-user: add target_sigdelset() and target_sigorset()
  [RFC] linux-user: fix sigismember() check
  [RFC] linux-user: add functions for working with the target signal
    mask
  [RFC] linux-user: add functionality for tracking target signal mask
  [RFC] linux-user: add support for multiplexing larger target signals
  [RFC] linux-user: add support for multiplexing signals in
    rt_sigqueueinfo(), rt_tgsigqueueinfo(), kill() and tgkill()
    syscalls.

 linux-user/qemu.h         |  11 +++
 linux-user/signal.c       | 235 +++++++++++++++++++++++++++++++++++++++++++++-
 linux-user/strace.c       | 177 ++++++++++++++++++++++++++++++++--
 linux-user/strace.list    |  16 ++--
 linux-user/syscall.c      | 208 +++++++++++++++++++++++++++++++++++++---
 linux-user/syscall_defs.h |  32 +++++++
 6 files changed, 651 insertions(+), 28 deletions(-)

-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 01/16] linux-user: add strace for getuid(), gettid(), getppid(), geteuid()
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 23:33   ` Philippe Mathieu-Daudé
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 02/16] linux-user: add tkill(), tgkill() and rt_sigqueueinfo() strace Miloš Stojanović
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Improve strace support for syscalls getuid(), gettid(), getppid()
and geteuid(). Since these system calls don't have arguments, "%s()"
is added in the corresponding strace.list entry so that no arguments
are printed.

getuid:
Prior to this commit, typical strace output used to look like this:
4894 getuid(4894,0,0,274886293296,-3689348814741910323,4832615904) = 1000
After this commit, it looks like this:
4894 getuid() = 1000

gettid:
Prior to this commit, typical strace output used to look like this:
8307 gettid(0,0,64,0,4832630528,4832615840) = 8307
After this commit, it looks like this:
8307 gettid() = 8307

getppid:
Prior to this commit, typical strace output used to look like this:
20588 getppid(20588,64,0,4832630528,4832615888,0) = 20625
After this commit, it looks like this:
20588 getppid() = 20625

geteuid:
Prior to this commit, typical strace output used to look like this:
20588 geteuid(64,0,0,4832615888,0,-9151031864016699136) = 1000
After this commit, it looks like this:
20588 geteuid() = 1000

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/strace.list | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/linux-user/strace.list b/linux-user/strace.list
index 3b1282e..6e33788 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -290,7 +290,7 @@
 { TARGET_NR_getegid32, "getegid32" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_geteuid
-{ TARGET_NR_geteuid, "geteuid" , NULL, NULL, NULL },
+{ TARGET_NR_geteuid, "geteuid" , "%s()", NULL, NULL },
 #endif
 #ifdef TARGET_NR_geteuid32
 { TARGET_NR_geteuid32, "geteuid32" , NULL, NULL, NULL },
@@ -338,7 +338,7 @@
 { TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_getppid
-{ TARGET_NR_getppid, "getppid" , NULL, NULL, NULL },
+{ TARGET_NR_getppid, "getppid" , "%s()", NULL, NULL },
 #endif
 #ifdef TARGET_NR_getpriority
 { TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
@@ -381,13 +381,13 @@
   NULL, NULL },
 #endif
 #ifdef TARGET_NR_gettid
-{ TARGET_NR_gettid, "gettid" , NULL, NULL, NULL },
+{ TARGET_NR_gettid, "gettid" , "%s()", NULL, NULL },
 #endif
 #ifdef TARGET_NR_gettimeofday
 { TARGET_NR_gettimeofday, "gettimeofday" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_getuid
-{ TARGET_NR_getuid, "getuid" , NULL, NULL, NULL },
+{ TARGET_NR_getuid, "getuid" , "%s()", NULL, NULL },
 #endif
 #ifdef TARGET_NR_getuid32
 { TARGET_NR_getuid32, "getuid32" , NULL, NULL, NULL },
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 02/16] linux-user: add tkill(), tgkill() and rt_sigqueueinfo() strace
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 01/16] linux-user: add strace for getuid(), gettid(), getppid(), geteuid() Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-06-02 12:31   ` Peter Maydell
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 03/16] linux-user: fix ssetmask() system call Miloš Stojanović
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Improve strace support for syscall tkill(), tgkill() and rt_sigqueueinfo()
by implementing print functions that match arguments types of the system
calls and add them to the corresponding starce.list entry.

tkill:
Prior to this commit, typical strace output used to look like this:
4886 tkill(4886,50,0,4832615904,0,-9151031864016699136) = 0
After this commit, it looks like this:
4886 tkill(4886,50) = 0

tgkill:
Prior to this commit, typical strace output used to look like this:
4890 tgkill(4890,4890,50,8,4832630528,4832615904) = 0
After this commit, it looks like this:
4890 tgkill(4890,4890,50) = 0

rt_sigqueueinfo:
Prior to this commit, typical strace output used to look like this:
8307 rt_sigqueueinfo(8307,50,1996483164,0,0,50) = 0
After this commit, it looks like this:
8307 rt_sigqueueinfo(8307,50,0x00000040007ff6b0) = 0

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/strace.c    | 41 +++++++++++++++++++++++++++++++++++++++++
 linux-user/strace.list |  6 +++---
 2 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 8fb1b6e..f6f76a5 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1901,6 +1901,20 @@ print_rt_sigprocmask(const struct syscallname *name,
 }
 #endif
 
+#ifdef TARGET_NR_rt_sigqueueinfo
+static void
+print_rt_sigqueueinfo(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    print_syscall_prologue(name);
+    print_raw_param("%d", arg0, 0);
+    print_signal(arg1, 0);
+    print_pointer(arg2, 1);
+    print_syscall_epilogue(name);
+}
+#endif
+
 #ifdef TARGET_NR_syslog
 static void
 print_syslog_action(abi_ulong arg, int last)
@@ -2415,6 +2429,33 @@ print_kill(const struct syscallname *name,
 }
 #endif
 
+#ifdef TARGET_NR_tkill
+static void
+print_tkill(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    print_syscall_prologue(name);
+    print_raw_param("%d", arg0, 0);
+    print_signal(arg1, 1);
+    print_syscall_epilogue(name);
+}
+#endif
+
+#ifdef TARGET_NR_tgkill
+static void
+print_tgkill(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    print_syscall_prologue(name);
+    print_raw_param("%d", arg0, 0);
+    print_raw_param("%d", arg1, 0);
+    print_signal(arg2, 1);
+    print_syscall_epilogue(name);
+}
+#endif
+
 /*
  * An array of all of the syscalls we know about
  */
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 6e33788..373d436 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1155,7 +1155,7 @@
 { TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, print_rt_sigprocmask, NULL },
 #endif
 #ifdef TARGET_NR_rt_sigqueueinfo
-{ TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, NULL, NULL },
+{ TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL },
 #endif
 #ifdef TARGET_NR_rt_sigreturn
 { TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL },
@@ -1498,7 +1498,7 @@
 { TARGET_NR_tee, "tee" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_tgkill
-{ TARGET_NR_tgkill, "tgkill" , NULL, NULL, NULL },
+{ TARGET_NR_tgkill, "tgkill" , NULL, print_tgkill, NULL },
 #endif
 #ifdef TARGET_NR_time
 { TARGET_NR_time, "time" , NULL, NULL, NULL },
@@ -1534,7 +1534,7 @@
 { TARGET_NR_times, "times" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_tkill
-{ TARGET_NR_tkill, "tkill" , NULL, NULL, NULL },
+{ TARGET_NR_tkill, "tkill" , NULL, print_tkill, NULL },
 #endif
 #ifdef TARGET_NR_truncate
 { TARGET_NR_truncate, "truncate" , NULL, NULL, NULL },
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 03/16] linux-user: fix ssetmask() system call
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 01/16] linux-user: add strace for getuid(), gettid(), getppid(), geteuid() Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 02/16] linux-user: add tkill(), tgkill() and rt_sigqueueinfo() strace Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 04/16] linux-user: fix mismatch of lock/unlock_user() invocations in rt_sigqueinfo() syscall Miloš Stojanović
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Fix the ssetmask() system call by removing the invocation of sigorset().

The ssetmask() system call should replace the old signal mask
with the new and return the old mask. It shouldn't combine
the old and the new mask with sigorset(). Fetching the old
mask for sigorset() is also no longer needed.

The problem was detected after running LTP test group syscalls
for the MIPS EL 32 R2 architecture where the test ssetmask01 failed
with exit code 1. The test passes now that the ssetmask() system call
is fixed.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/syscall.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index cec8428..abba3d8 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8592,17 +8592,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR_ssetmask /* not on alpha */
     case TARGET_NR_ssetmask:
         {
-            sigset_t set, oset, cur_set;
+            sigset_t set, oset;
             abi_ulong target_set = arg1;
-            /* We only have one word of the new mask so we must read
-             * the rest of it with do_sigprocmask() and OR in this word.
-             * We are guaranteed that a do_sigprocmask() that only queries
-             * the signal mask will not fail.
-             */
-            ret = do_sigprocmask(0, NULL, &cur_set);
-            assert(!ret);
             target_to_host_old_sigset(&set, &target_set);
-            sigorset(&set, &set, &cur_set);
             ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
             if (!ret) {
                 host_to_target_old_sigset(&target_set, &oset);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 04/16] linux-user: fix mismatch of lock/unlock_user() invocations in rt_sigqueinfo() syscall
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (2 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 03/16] linux-user: fix ssetmask() system call Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 05/16] linux-user: fix argument type declaration of " Miloš Stojanović
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Change the unlock_user() argument from arg1 to arg3 to match with
lock_user(), since arg3 contains the pointer to the siginfo_t structure.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/syscall.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index abba3d8..ff03e1a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8839,7 +8839,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 goto efault;
             }
             target_to_host_siginfo(&uinfo, p);
-            unlock_user(p, arg1, 0);
+            unlock_user(p, arg3, 0);
             ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
         }
         break;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 05/16] linux-user: fix argument type declaration of rt_sigqueinfo() syscall
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (3 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 04/16] linux-user: fix mismatch of lock/unlock_user() invocations in rt_sigqueinfo() syscall Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 23:35   ` Philippe Mathieu-Daudé
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 06/16] linux-user: add support for rt_tgsigqueueinfo() system call Miloš Stojanović
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Change the type of the first argument of rt_sigqueinfo() from int to pid_t
in the syscall declaration to match specifications of the system call.

Proper spacing is added to satisfy checkpatch.pl.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/syscall.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ff03e1a..9ec7ccd 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -274,7 +274,7 @@ _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, co
 _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
           loff_t *, res, uint, wh);
 #endif
-_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
+_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
 _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #ifdef __NR_exit_group
 _syscall1(int,exit_group,int,error_code)
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 06/16] linux-user: add support for rt_tgsigqueueinfo() system call
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (4 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 05/16] linux-user: fix argument type declaration of " Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 07/16] linux-user: add rt_tgsigqueueinfo() strace Miloš Stojanović
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Add a new system call: rt_tgsigqueueinfo().

This system call is similar to rt_sigqueueinfo(), but instead of
sending the signal and data to the whole thread group with the ID
equal to the argument tgid, it sends it to a single thread within
that thread group. The ID of the thread is specified by the tid
argument.

The implementation is based on the rt_sigqueueinfo() in linux-user
mode, where the tid is added as the second argument and the
previous second and third argument become arguments three and four,
respectively.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>

Conflicts:
	linux-user/syscall.c
---
 linux-user/syscall.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 9ec7ccd..d3b769e 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -238,6 +238,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,	\
 #define __NR_sys_getdents64 __NR_getdents64
 #define __NR_sys_getpriority __NR_getpriority
 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
+#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
 #define __NR_sys_syslog __NR_syslog
 #define __NR_sys_futex __NR_futex
 #define __NR_sys_inotify_init __NR_inotify_init
@@ -275,6 +276,8 @@ _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
           loff_t *, res, uint, wh);
 #endif
 _syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
+_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
+          siginfo_t *, uinfo)
 _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
 #ifdef __NR_exit_group
 _syscall1(int,exit_group,int,error_code)
@@ -8843,6 +8846,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
         }
         break;
+    case TARGET_NR_rt_tgsigqueueinfo:
+        {
+            siginfo_t uinfo;
+
+            p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
+            if (!p) {
+                goto efault;
+            }
+            target_to_host_siginfo(&uinfo, p);
+            unlock_user(p, arg4, 0);
+            ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
+        }
+        break;
 #ifdef TARGET_NR_sigreturn
     case TARGET_NR_sigreturn:
         if (block_signals()) {
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 07/16] linux-user: add rt_tgsigqueueinfo() strace
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (5 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 06/16] linux-user: add support for rt_tgsigqueueinfo() system call Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 08/16] linux-user: fix inconsistent spaces in print_siginfo() output Miloš Stojanović
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

This commit improves strace support for syscall rt_tgsigqueueinfo().

Prior to this commit, typical strace output used to look like this:
7775 rt_tgsigqueueinfo(7775,7775,50,1996483164,0,0) = 0

After this commit, it looks like this:
7775 rt_tgsigqueueinfo(7775,7775,50,0x76ffea5c) = 0

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/strace.c    | 15 +++++++++++++++
 linux-user/strace.list |  2 +-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index f6f76a5..779cda1 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1915,6 +1915,21 @@ print_rt_sigqueueinfo(const struct syscallname *name,
 }
 #endif
 
+#ifdef TARGET_NR_rt_tgsigqueueinfo
+static void
+print_rt_tgsigqueueinfo(const struct syscallname *name,
+    abi_long arg0, abi_long arg1, abi_long arg2,
+    abi_long arg3, abi_long arg4, abi_long arg5)
+{
+    print_syscall_prologue(name);
+    print_raw_param("%d", arg0, 0);
+    print_raw_param("%d", arg1, 0);
+    print_signal(arg2, 0);
+    print_pointer(arg3, 1);
+    print_syscall_epilogue(name);
+}
+#endif
+
 #ifdef TARGET_NR_syslog
 static void
 print_syslog_action(abi_ulong arg, int last)
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 373d436..a91e33f 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -1167,7 +1167,7 @@
 { TARGET_NR_rt_sigtimedwait, "rt_sigtimedwait" , NULL, NULL, NULL },
 #endif
 #ifdef TARGET_NR_rt_tgsigqueueinfo
-{ TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, NULL, NULL },
+{ TARGET_NR_rt_tgsigqueueinfo, "rt_tgsigqueueinfo" , NULL, print_rt_tgsigqueueinfo, NULL },
 #endif
 #ifdef TARGET_NR_sched_getaffinity
 { TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL },
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 08/16] linux-user: fix inconsistent spaces in print_siginfo() output
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (6 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 07/16] linux-user: add rt_tgsigqueueinfo() strace Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 09/16] linux-user: add strace support for uinfo structure of rt_sigqueueinfo() and rt_tgsigqueueinfo() Miloš Stojanović
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

This patch improves the consistentcy of the output from print_siginfo()
by removing spaces around the equal sign of si_pid, si_uid, si_timer1,
si_timer2, si_band, si_fd, si_addr, si_status and si_sigval. This way
they match si_signo and ci_code. Host strace was used as a reference
for this chage.

Prior to this commit, typical strace output used to look like this:
--- 64 {si_signo=64, si_code=SI_TKILL, si_pid = 22845, si_uid = 1000} ---

After this commit, it looks like this:
--- 64 {si_signo=64, si_code=SI_TKILL, si_pid=22845, si_uid=1000} ---

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/strace.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 779cda1..5fbe067 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -206,26 +206,26 @@ static void print_siginfo(const target_siginfo_t *tinfo)
 
     switch (si_type) {
     case QEMU_SI_KILL:
-        gemu_log(", si_pid = %u, si_uid = %u",
+        gemu_log(", si_pid=%u, si_uid=%u",
                  (unsigned int)tinfo->_sifields._kill._pid,
                  (unsigned int)tinfo->_sifields._kill._uid);
         break;
     case QEMU_SI_TIMER:
-        gemu_log(", si_timer1 = %u, si_timer2 = %u",
+        gemu_log(", si_timer1=%u, si_timer2=%u",
                  tinfo->_sifields._timer._timer1,
                  tinfo->_sifields._timer._timer2);
         break;
     case QEMU_SI_POLL:
-        gemu_log(", si_band = %d, si_fd = %d",
+        gemu_log(", si_band=%d, si_fd=%d",
                  tinfo->_sifields._sigpoll._band,
                  tinfo->_sifields._sigpoll._fd);
         break;
     case QEMU_SI_FAULT:
-        gemu_log(", si_addr = ");
+        gemu_log(", si_addr=");
         print_pointer(tinfo->_sifields._sigfault._addr, 1);
         break;
     case QEMU_SI_CHLD:
-        gemu_log(", si_pid = %u, si_uid = %u, si_status = %d"
+        gemu_log(", si_pid=%u, si_uid=%u, si_status=%d"
                  ", si_utime=" TARGET_ABI_FMT_ld
                  ", si_stime=" TARGET_ABI_FMT_ld,
                  (unsigned int)(tinfo->_sifields._sigchld._pid),
@@ -235,7 +235,7 @@ static void print_siginfo(const target_siginfo_t *tinfo)
                  tinfo->_sifields._sigchld._stime);
         break;
     case QEMU_SI_RT:
-        gemu_log(", si_pid = %u, si_uid = %u, si_sigval = " TARGET_ABI_FMT_ld,
+        gemu_log(", si_pid=%u, si_uid=%u, si_sigval=" TARGET_ABI_FMT_ld,
                  (unsigned int)tinfo->_sifields._rt._pid,
                  (unsigned int)tinfo->_sifields._rt._uid,
                  tinfo->_sifields._rt._sigval.sival_ptr);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 09/16] linux-user: add strace support for uinfo structure of rt_sigqueueinfo() and rt_tgsigqueueinfo()
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (7 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 08/16] linux-user: fix inconsistent spaces in print_siginfo() output Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 10/16] [RFC] linux-user: add support for tracking the target signal mask Miloš Stojanović
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

This commit adds support for printing the content of the target_siginfo_t
structure in a similar way to how it is printed by the host strace. The
pointer to this structure is sent as the last argument of the
rt_sigqueueinfo() and rt_tgsigqueueinfo() system calls.
For this purpose, print_siginfo() is used and the get_target_siginfo()
function is implemented in order to get the information obtained from
the pointer into the form that print_siginfo() expects.

The get_target_siginfo() function is based on
host_to_target_siginfo_noswap() in linux-user mode, but here both
arguments are pointers to target_siginfo_t, so instead of converting
the information to siginfo_t it just extracts and copies it to a
target_siginfo_t structure.

Prior to this commit, typical strace output used to look like this:
8307 rt_sigqueueinfo(8307,50,0x00000040007ff6b0) = 0

After this commit, it looks like this:
8307 rt_sigqueueinfo(8307,50,{si_signo=50, si_code=SI_QUEUE, si_pid=8307,
si_uid=1000, si_sigval=17716762128}) = 0

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/strace.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 111 insertions(+), 2 deletions(-)

diff --git a/linux-user/strace.c b/linux-user/strace.c
index 5fbe067..d821d16 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -188,6 +188,93 @@ static void print_si_code(int arg)
     gemu_log("%s", codename);
 }
 
+static void get_target_siginfo(target_siginfo_t *tinfo,
+                                const target_siginfo_t *info)
+{
+    abi_ulong sival_ptr;
+
+    int sig;
+    int si_errno;
+    int si_code;
+    int si_type;
+
+    __get_user(sig, &info->si_signo);
+    __get_user(si_errno, &tinfo->si_errno);
+    __get_user(si_code, &info->si_code);
+
+    tinfo->si_signo = sig;
+    tinfo->si_errno = si_errno;
+    tinfo->si_code = si_code;
+
+    /* Ensure we don't leak random junk to the guest later */
+    memset(tinfo->_sifields._pad, 0, sizeof(tinfo->_sifields._pad));
+
+    /* This is awkward, because we have to use a combination of
+     * the si_code and si_signo to figure out which of the union's
+     * members are valid. (Within the host kernel it is always possible
+     * to tell, but the kernel carefully avoids giving userspace the
+     * high 16 bits of si_code, so we don't have the information to
+     * do this the easy way...) We therefore make our best guess,
+     * bearing in mind that a guest can spoof most of the si_codes
+     * via rt_sigqueueinfo() if it likes.
+     *
+     * Once we have made our guess, we record it in the top 16 bits of
+     * the si_code, so that print_siginfo() later can use it.
+     * print_siginfo() will strip these top bits out before printing
+     * the si_code.
+     */
+
+    switch (si_code) {
+    case SI_USER:
+    case SI_TKILL:
+    case SI_KERNEL:
+        /* Sent via kill(), tkill() or tgkill(), or direct from the kernel.
+         * These are the only unspoofable si_code values.
+         */
+        __get_user(tinfo->_sifields._kill._pid, &info->_sifields._kill._pid);
+        __get_user(tinfo->_sifields._kill._uid, &info->_sifields._kill._uid);
+        si_type = QEMU_SI_KILL;
+        break;
+    default:
+        /* Everything else is spoofable. Make best guess based on signal */
+        switch (sig) {
+        case TARGET_SIGCHLD:
+            __get_user(tinfo->_sifields._sigchld._pid,
+                       &info->_sifields._sigchld._pid);
+            __get_user(tinfo->_sifields._sigchld._uid,
+                       &info->_sifields._sigchld._uid);
+            __get_user(tinfo->_sifields._sigchld._status,
+                       &info->_sifields._sigchld._status);
+            __get_user(tinfo->_sifields._sigchld._utime,
+                       &info->_sifields._sigchld._utime);
+            __get_user(tinfo->_sifields._sigchld._stime,
+                       &info->_sifields._sigchld._stime);
+            si_type = QEMU_SI_CHLD;
+            break;
+        case TARGET_SIGIO:
+            __get_user(tinfo->_sifields._sigpoll._band,
+                       &info->_sifields._sigpoll._band);
+            __get_user(tinfo->_sifields._sigpoll._fd,
+                       &info->_sifields._sigpoll._fd);
+            si_type = QEMU_SI_POLL;
+            break;
+        default:
+            /* Assume a sigqueue()/mq_notify()/rt_sigqueueinfo() source. */
+            __get_user(tinfo->_sifields._rt._pid, &info->_sifields._rt._pid);
+            __get_user(tinfo->_sifields._rt._uid, &info->_sifields._rt._uid);
+            /* XXX: potential problem if 64 bit */
+            __get_user(sival_ptr, &info->_sifields._rt._sigval.sival_ptr);
+            tinfo->_sifields._rt._sigval.sival_ptr = sival_ptr;
+
+            si_type = QEMU_SI_RT;
+            break;
+        }
+        break;
+    }
+
+    tinfo->si_code = deposit32(si_code, 16, 16, si_type);
+}
+
 static void print_siginfo(const target_siginfo_t *tinfo)
 {
     /* Print a target_siginfo_t in the format desired for printing
@@ -1907,10 +1994,21 @@ print_rt_sigqueueinfo(const struct syscallname *name,
     abi_long arg0, abi_long arg1, abi_long arg2,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
+    void *p;
+    target_siginfo_t uinfo;
+
     print_syscall_prologue(name);
     print_raw_param("%d", arg0, 0);
     print_signal(arg1, 0);
-    print_pointer(arg2, 1);
+    p = lock_user(VERIFY_READ, arg2, sizeof(target_siginfo_t), 1);
+    if (p) {
+        get_target_siginfo(&uinfo, p);
+        print_siginfo(&uinfo);
+
+        unlock_user(p, arg2, 0);
+    } else {
+        print_pointer(arg2, 1);
+    }
     print_syscall_epilogue(name);
 }
 #endif
@@ -1921,11 +2019,22 @@ print_rt_tgsigqueueinfo(const struct syscallname *name,
     abi_long arg0, abi_long arg1, abi_long arg2,
     abi_long arg3, abi_long arg4, abi_long arg5)
 {
+    void *p;
+    target_siginfo_t uinfo;
+
     print_syscall_prologue(name);
     print_raw_param("%d", arg0, 0);
     print_raw_param("%d", arg1, 0);
     print_signal(arg2, 0);
-    print_pointer(arg3, 1);
+    p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
+    if (p) {
+        get_target_siginfo(&uinfo, p);
+        print_siginfo(&uinfo);
+
+        unlock_user(p, arg3, 0);
+    } else {
+        print_pointer(arg3, 1);
+    }
     print_syscall_epilogue(name);
 }
 #endif
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 10/16] [RFC] linux-user: add support for tracking the target signal mask
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (8 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 09/16] linux-user: add strace support for uinfo structure of rt_sigqueueinfo() and rt_tgsigqueueinfo() Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 11/16] [RFC] linux-user: add target_sigdelset() and target_sigorset() Miloš Stojanović
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

If TRACK_TARGET_SIGMASK is defined, add fields in the TaskState structure
which will hold the target signal and suspend mask and add support for
initialization and forking. No functional changes are being introduced in
this commit. The TRACK_TARGET_SIGMASK will be defined in a later commit
where the target signal masks will be needed in order to implement
multiplexing of real-time target signals which are out of the host range.

Currently, QEMU has a copy of the host signal and suspend masks and that
is usually enough, since most of the time the signal mask of the target
architecture is either the same length or narrower. If however the signal
mask is wider, then part of it won't be tracked.

This commit enables adding support for separately tracking the target
signal masks in the following commits.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/qemu.h    | 5 +++++
 linux-user/signal.c  | 3 +++
 linux-user/syscall.c | 3 +++
 3 files changed, 11 insertions(+)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 4edd7d0..6ce0811 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -139,6 +139,11 @@ typedef struct TaskState {
      * currently in the middle of such a syscall
      */
     sigset_t sigsuspend_mask;
+#ifdef TRACK_TARGET_SIGMASK
+    /* Track the target signal and suspend masks. */
+    target_sigset_t target_signal_mask;
+    target_sigset_t target_sigsuspend_mask;
+#endif
     /* Nonzero if we're leaving a sigsuspend and sigsuspend_mask is valid. */
     int in_sigsuspend;
 
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 3d18d1b..54c3be7 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -485,6 +485,9 @@ void signal_init(void)
 
     /* Set the signal mask from the host mask. */
     sigprocmask(0, 0, &ts->signal_mask);
+#ifdef TRACK_TARGET_SIGMASK
+    host_to_target_sigset_internal(&ts->target_signal_mask, &ts->signal_mask);
+#endif
 
     /* set all host signal handlers. ALL signals are blocked during
        the handlers to serialize them. */
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index d3b769e..94ecae3 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -6279,6 +6279,9 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
         ts->bprm = parent_ts->bprm;
         ts->info = parent_ts->info;
         ts->signal_mask = parent_ts->signal_mask;
+#ifdef TRACK_TARGET_SIGMASK
+        ts->target_signal_mask = parent_ts->target_signal_mask;
+#endif
 
         if (flags & CLONE_CHILD_CLEARTID) {
             ts->child_tidptr = child_tidptr;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 11/16] [RFC] linux-user: add target_sigdelset() and target_sigorset()
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (9 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 10/16] [RFC] linux-user: add support for tracking the target signal mask Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 12/16] [RFC] linux-user: fix sigismember() check Miloš Stojanović
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Add two inline functions that work with the signal set of the target.

target_sigdelset() removes a signal from target_sigset_t.
target_sigorset() creates a union of two target_sigset_t.

These functions will be used for introducing support for tracking the
target signal set. Functions for emptying and adding into a target signal
set already exist so this commit will serve as a supplement.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/signal.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 54c3be7..ae4da79 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -120,6 +120,12 @@ static inline void target_sigaddset(target_sigset_t *set, int signum)
     set->sig[signum / TARGET_NSIG_BPW] |= mask;
 }
 
+static inline void target_sigdelset(target_sigset_t *set, int signum)
+{
+    abi_ulong mask = (abi_ulong)1 << (--signum % TARGET_NSIG_BPW);
+    set->sig[signum / TARGET_NSIG_BPW] &= ~mask;
+}
+
 static inline int target_sigismember(const target_sigset_t *set, int signum)
 {
     signum--;
@@ -127,6 +133,16 @@ static inline int target_sigismember(const target_sigset_t *set, int signum)
     return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
 }
 
+static inline void target_sigorset(target_sigset_t *set,
+                                   const target_sigset_t *left,
+                                   const target_sigset_t *right)
+{
+    int i;
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        set->sig[i] = left->sig[i] | right->sig[i];
+    }
+}
+
 static void host_to_target_sigset_internal(target_sigset_t *d,
                                            const sigset_t *s)
 {
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 12/16] [RFC] linux-user: fix sigismember() check
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (10 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 11/16] [RFC] linux-user: add target_sigdelset() and target_sigorset() Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 13/16] [RFC] linux-user: add functions for working with the target signal mask Miloš Stojanović
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Fix copying between the host and target signal sets for the case when the
target set is larger than the host set.

sigismember() returns 1 if the specified signal number is a member of
the specified signal set, but it can also return -1 if an error occurs
(e.g. an out of range signal number is specified). All non-zero values
would cause the signal to be added, so a comparison with 1 is added to
assure that only the signals which are really in the set get added to
the other set.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/signal.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index ae4da79..b96d508 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -149,7 +149,7 @@ static void host_to_target_sigset_internal(target_sigset_t *d,
     int i;
     target_sigemptyset(d);
     for (i = 1; i <= TARGET_NSIG; i++) {
-        if (sigismember(s, i)) {
+        if (sigismember(s, i) == 1) {
             target_sigaddset(d, host_to_target_signal(i));
         }
     }
@@ -171,7 +171,7 @@ static void target_to_host_sigset_internal(sigset_t *d,
     int i;
     sigemptyset(d);
     for (i = 1; i <= TARGET_NSIG; i++) {
-        if (target_sigismember(s, i)) {
+        if (target_sigismember(s, i) == 1) {
             sigaddset(d, target_to_host_signal(i));
         }
     }
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 13/16] [RFC] linux-user: add functions for working with the target signal mask
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (11 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 12/16] [RFC] linux-user: fix sigismember() check Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 14/16] [RFC] linux-user: add functionality for tracking " Miloš Stojanović
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Add functions tswapal_target_sigset(), target_to_abi_ulong_old_sigset()
and abi_ulong_to_target_old_sigset().

The tswapal_target_sigset() function transforms target signal sets
from target to host endianness. This is helpful for tracking and working
with the target signal masks in the host endianness rather then keeping
it in the target endianness.

The target_to_abi_ulong_old_sigset() and abi_ulong_to_target_old_sigset()
functions are used for translating the signal set between the old way of
storing it in abi_ulong and the new target_sigset_t structure. They can
be used for expanding old implementations of certain system calls to
include the tracking of the target signal masks.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
Change from v1 to v2:
tswapal_target_sigset() is no longer static since it was breaking the build.

 linux-user/qemu.h         |  1 +
 linux-user/signal.c       | 27 +++++++++++++++++++++++++++
 linux-user/syscall_defs.h |  4 ++++
 3 files changed, 32 insertions(+)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 6ce0811..7049517 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -391,6 +391,7 @@ void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
 void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
 int target_to_host_signal(int sig);
 int host_to_target_signal(int sig);
+void tswapal_target_sigset(target_sigset_t *d, const target_sigset_t *s);
 long do_sigreturn(CPUArchState *env);
 long do_rt_sigreturn(CPUArchState *env);
 abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
diff --git a/linux-user/signal.c b/linux-user/signal.c
index b96d508..5c441db 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -207,6 +207,33 @@ void target_to_host_old_sigset(sigset_t *sigset,
     target_to_host_sigset(sigset, &d);
 }
 
+void target_to_abi_ulong_old_sigset(abi_ulong *old_sigset,
+                                    const target_sigset_t *target_sigset)
+{
+    target_sigset_t d;
+    tswapal_target_sigset(&d, target_sigset);
+
+    memcpy(old_sigset, &d.sig, sizeof(target_sigset_t));
+}
+
+void abi_ulong_to_target_old_sigset(target_sigset_t *target_sigset,
+                                    const abi_ulong *old_sigset)
+{
+    target_sigset_t d;
+
+    memcpy(&d.sig, old_sigset, sizeof(target_sigset_t));
+    tswapal_target_sigset(target_sigset, &d);
+}
+
+void tswapal_target_sigset(target_sigset_t *d, const target_sigset_t *s)
+{
+    int i;
+
+    for (i = 0; i < TARGET_NSIG_WORDS; i++) {
+        d->sig[i] = tswapal(s->sig[i]);
+    }
+}
+
 int block_signals(void)
 {
     TaskState *ts = (TaskState *)thread_cpu->opaque;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 40c5027..7eec420 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -426,6 +426,10 @@ void host_to_target_old_sigset(abi_ulong *old_sigset,
                                const sigset_t *sigset);
 void target_to_host_old_sigset(sigset_t *sigset,
                                const abi_ulong *old_sigset);
+void target_to_abi_ulong_old_sigset(abi_ulong *old_sigset,
+                                    const target_sigset_t *target_sigset);
+void abi_ulong_to_target_old_sigset(target_sigset_t *target_sigset,
+                                    const abi_ulong *old_sigset);
 struct target_sigaction;
 int do_sigaction(int sig, const struct target_sigaction *act,
                  struct target_sigaction *oact);
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 14/16] [RFC] linux-user: add functionality for tracking target signal mask
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (12 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 13/16] [RFC] linux-user: add functions for working with the target signal mask Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 15/16] [RFC] linux-user: add support for multiplexing larger target signals Miloš Stojanović
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Add support for tracking the larger target signal mask in system calls
sigprocmask()/rt_sigprocmask(), sigsuspend()/rt_sigsuspend(),
sgetmask()/ssetmask() and in functions do_sigreturn(), do_rt_sigreturn(),
handle_pending_signal(), process_pending_signals().
Add a new function do_target_sigprocmask() which is based on
do_sigprocmask() and extends its functionallity.

It can happen that the host machine has a smaller range of signals
compared to the target machine that it's emulating. Currently the signals
that are in the target range but out of the host range are treated like
faulty signals and can't be used. In this patch, support is added for
tracking the target signal mask, alongside and in the same manner as the
host signal mask.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/qemu.h    |   5 ++
 linux-user/signal.c  | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 linux-user/syscall.c |  94 ++++++++++++++++++++++++++++++++++++
 3 files changed, 229 insertions(+), 1 deletion(-)

diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 7049517..3bbc642 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -396,6 +396,11 @@ long do_sigreturn(CPUArchState *env);
 long do_rt_sigreturn(CPUArchState *env);
 abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
 int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
+#ifdef TRACK_TARGET_SIGMASK
+int do_target_sigprocmask(int how, const target_sigset_t *target_set,
+                          target_sigset_t *target_oldset,
+                          const sigset_t *set, sigset_t *oldset);
+#endif
 /**
  * block_signals: block all signals while handling this guest syscall
  *
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 5c441db..006b45b 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -296,17 +296,85 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
     return 0;
 }
 
+#ifdef TRACK_TARGET_SIGMASK
+int do_target_sigprocmask(int how, const target_sigset_t *target_set,
+                          target_sigset_t *target_oldset,
+                          const sigset_t *set, sigset_t *oldset)
+{
+    TaskState *ts = (TaskState *)thread_cpu->opaque;
+
+    if (target_oldset) {
+        *target_oldset = ts->target_signal_mask;
+    }
+    if (oldset) {
+        *oldset = ts->signal_mask;
+    }
+
+    if (target_set && set) {
+        int i;
+
+        if (block_signals()) {
+            return -TARGET_ERESTARTSYS;
+        }
+
+        switch (how) {
+        case SIG_BLOCK:
+            target_sigorset(&ts->target_signal_mask, &ts->target_signal_mask,
+                            target_set);
+            sigorset(&ts->signal_mask, &ts->signal_mask, set);
+            break;
+        case SIG_UNBLOCK:
+            for (i = 1; i <= TARGET_NSIG; ++i) {
+                if (target_sigismember(target_set, i) == 1) {
+                    target_sigdelset(&ts->target_signal_mask, i);
+                }
+            }
+            for (i = 1; i <= NSIG; ++i) {
+                if (sigismember(set, i) == 1) {
+                    sigdelset(&ts->signal_mask, i);
+                }
+            }
+            break;
+        case SIG_SETMASK:
+            ts->target_signal_mask = *target_set;
+            ts->signal_mask = *set;
+            break;
+        default:
+            g_assert_not_reached();
+        }
+
+        /* Silently ignore attempts to change blocking status of KILL or STOP */
+        target_sigdelset(&ts->target_signal_mask, SIGKILL);
+        target_sigdelset(&ts->target_signal_mask, SIGSTOP);
+        sigdelset(&ts->signal_mask, SIGKILL);
+        sigdelset(&ts->signal_mask, SIGSTOP);
+    }
+    return 0;
+}
+#endif
+
 #if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
     !defined(TARGET_NIOS2)
 /* Just set the guest's signal mask to the specified value; the
  * caller is assumed to have called block_signals() already.
  */
+#ifndef TRACK_TARGET_SIGMASK
 static void set_sigmask(const sigset_t *set)
 {
     TaskState *ts = (TaskState *)thread_cpu->opaque;
 
     ts->signal_mask = *set;
 }
+#else
+static void target_set_sigmask(const sigset_t *set,
+                               const target_sigset_t *target_set)
+{
+    TaskState *ts = (TaskState *)thread_cpu->opaque;
+
+    ts->signal_mask = *set;
+    ts->target_signal_mask = *target_set;
+}
+#endif
 #endif
 
 /* siginfo conversion */
@@ -3315,6 +3383,9 @@ long do_sigreturn(CPUMIPSState *regs)
     abi_ulong frame_addr;
     sigset_t blocked;
     target_sigset_t target_set;
+#ifdef TRACK_TARGET_SIGMASK
+    target_sigset_t target_blocked;
+#endif
     int i;
 
     frame_addr = regs->active_tc.gpr[29];
@@ -3327,7 +3398,12 @@ long do_sigreturn(CPUMIPSState *regs)
     }
 
     target_to_host_sigset_internal(&blocked, &target_set);
+#ifdef TRACK_TARGET_SIGMASK
+    tswapal_target_sigset(&target_blocked, &target_set);
+    target_set_sigmask(&blocked, &target_blocked);
+#else
     set_sigmask(&blocked);
+#endif
 
     restore_sigcontext(regs, &frame->sf_sc);
 
@@ -3423,6 +3499,9 @@ long do_rt_sigreturn(CPUMIPSState *env)
     struct target_rt_sigframe *frame;
     abi_ulong frame_addr;
     sigset_t blocked;
+#ifdef TRACK_TARGET_SIGMASK
+    target_sigset_t target_blocked;
+#endif
 
     frame_addr = env->active_tc.gpr[29];
     trace_user_do_rt_sigreturn(env, frame_addr);
@@ -3431,7 +3510,12 @@ long do_rt_sigreturn(CPUMIPSState *env)
     }
 
     target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
+#ifdef TRACK_TARGET_SIGMASK
+    tswapal_target_sigset(&target_blocked, &frame->rs_uc.tuc_sigmask);
+    target_set_sigmask(&blocked, &target_blocked);
+#else
     set_sigmask(&blocked);
+#endif
 
     restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
 
@@ -6575,6 +6659,9 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
     abi_ulong handler;
     sigset_t set;
     target_sigset_t target_old_set;
+#ifdef TRACK_TARGET_SIGMASK
+    target_sigset_t target_set;
+#endif
     struct target_sigaction *sa;
     TaskState *ts = cpu->opaque;
 
@@ -6612,21 +6699,39 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
     } else {
         /* compute the blocked signals during the handler execution */
         sigset_t *blocked_set;
+#ifdef TRACK_TARGET_SIGMASK
+        target_sigset_t *target_blocked_set;
 
+        tswapal_target_sigset(&target_set, &sa->sa_mask);
+#endif
         target_to_host_sigset(&set, &sa->sa_mask);
         /* SA_NODEFER indicates that the current signal should not be
            blocked during the handler */
-        if (!(sa->sa_flags & TARGET_SA_NODEFER))
+        if (!(sa->sa_flags & TARGET_SA_NODEFER)) {
+#ifdef TRACK_TARGET_SIGMASK
+            target_sigaddset(&target_set, sig);
+#endif
             sigaddset(&set, target_to_host_signal(sig));
+        }
 
         /* save the previous blocked signal state to restore it at the
            end of the signal execution (see do_sigreturn) */
+#ifdef TRACK_TARGET_SIGMASK
+        target_old_set = ts->target_signal_mask;
+#else
         host_to_target_sigset_internal(&target_old_set, &ts->signal_mask);
+#endif
 
         /* block signals in the handler */
         blocked_set = ts->in_sigsuspend ?
             &ts->sigsuspend_mask : &ts->signal_mask;
         sigorset(&ts->signal_mask, blocked_set, &set);
+#ifdef TRACK_TARGET_SIGMASK
+        target_blocked_set = ts->in_sigsuspend ?
+            &ts->target_sigsuspend_mask : &ts->target_signal_mask;
+        target_sigorset(&ts->target_signal_mask, target_blocked_set,
+                        &target_set);
+#endif
         ts->in_sigsuspend = 0;
 
         /* if the CPU is in VM86 mode, we restore the 32 bit values */
@@ -6662,7 +6767,11 @@ void process_pending_signals(CPUArchState *cpu_env)
     int sig;
     TaskState *ts = cpu->opaque;
     sigset_t set;
+#ifdef TRACK_TARGET_SIGMASK
+    target_sigset_t *target_blocked_set;
+#else
     sigset_t *blocked_set;
+#endif
 
     while (atomic_read(&ts->signal_pending)) {
         /* FIXME: This is not threadsafe.  */
@@ -6680,22 +6789,42 @@ void process_pending_signals(CPUArchState *cpu_env)
              * to block a synchronous signal since it could then just end up
              * looping round and round indefinitely.
              */
+#ifdef TRACK_TARGET_SIGMASK
+            if (sigismember(&ts->signal_mask, target_to_host_signal(sig)) == 1
+                || target_sigismember(&ts->target_signal_mask, sig) == 1
+                || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
+                sigdelset(&ts->signal_mask, target_to_host_signal(sig));
+                target_sigdelset(&ts->target_signal_mask, sig);
+                sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
+            }
+#else
             if (sigismember(&ts->signal_mask, target_to_host_signal_table[sig])
                 || sigact_table[sig - 1]._sa_handler == TARGET_SIG_IGN) {
                 sigdelset(&ts->signal_mask, target_to_host_signal_table[sig]);
                 sigact_table[sig - 1]._sa_handler = TARGET_SIG_DFL;
             }
+#endif
 
             handle_pending_signal(cpu_env, sig, &ts->sync_signal);
         }
 
         for (sig = 1; sig <= TARGET_NSIG; sig++) {
+#ifdef TRACK_TARGET_SIGMASK
+            target_blocked_set = ts->in_sigsuspend ?
+                &ts->target_sigsuspend_mask : &ts->target_signal_mask;
+#else
             blocked_set = ts->in_sigsuspend ?
                 &ts->sigsuspend_mask : &ts->signal_mask;
+#endif
 
+#ifdef TRACK_TARGET_SIGMASK
+            if (ts->sigtab[sig - 1].pending &&
+                (!target_sigismember(target_blocked_set, sig))) {
+#else
             if (ts->sigtab[sig - 1].pending &&
                 (!sigismember(blocked_set,
                               target_to_host_signal_table[sig]))) {
+#endif
                 handle_pending_signal(cpu_env, sig, &ts->sigtab[sig - 1]);
                 /* Restart scan from the beginning, as handle_pending_signal
                  * might have resulted in a new synchronous signal (eg SIGSEGV).
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 94ecae3..f4ce6a8 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -8585,6 +8585,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #ifdef TARGET_NR_sgetmask /* not on alpha */
     case TARGET_NR_sgetmask:
         {
+#ifdef TRACK_TARGET_SIGMASK
+            sigset_t cur_set;
+            target_sigset_t target_set_mask;
+            abi_ulong target_set;
+            ret = do_target_sigprocmask(0, NULL, &target_set_mask,
+                                        NULL, &cur_set);
+            if (!ret) {
+                target_to_abi_ulong_old_sigset(&target_set, &target_set_mask);
+                ret = target_set;
+            }
+#else
             sigset_t cur_set;
             abi_ulong target_set;
             ret = do_sigprocmask(0, NULL, &cur_set);
@@ -8592,12 +8603,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 host_to_target_old_sigset(&target_set, &cur_set);
                 ret = target_set;
             }
+#endif
         }
         break;
 #endif
 #ifdef TARGET_NR_ssetmask /* not on alpha */
     case TARGET_NR_ssetmask:
         {
+#ifdef TRACK_TARGET_SIGMASK
+            sigset_t set, oset;
+            target_sigset_t target_set_mask, target_oset;
+            abi_ulong target_set = arg1;
+            target_to_host_old_sigset(&set, &target_set);
+            abi_ulong_to_target_old_sigset(&target_set_mask, &target_set);
+            ret = do_target_sigprocmask(SIG_SETMASK, &target_set_mask,
+                                        &target_oset, &set, &oset);
+            if (!ret) {
+                target_to_abi_ulong_old_sigset(&target_set, &target_oset);
+                ret = target_set;
+            }
+#else
             sigset_t set, oset;
             abi_ulong target_set = arg1;
             target_to_host_old_sigset(&set, &target_set);
@@ -8606,6 +8631,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 host_to_target_old_sigset(&target_set, &oset);
                 ret = target_set;
             }
+#endif
         }
         break;
 #endif
@@ -8614,6 +8640,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
 #if defined(TARGET_ALPHA)
             sigset_t set, oldset;
+#ifdef TRACK_TARGET_SIGMASK
+            target_sigset_t target_set, target_oldset;
+#endif
             abi_ulong mask;
             int how;
 
@@ -8634,14 +8663,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             mask = arg2;
             target_to_host_old_sigset(&set, &mask);
 
+#ifdef TRACK_TARGET_SIGMASK
+            abi_ulong_to_target_old_sigset(&target_set, &mask);
+
+            ret = do_target_sigprocmask(how, &target_set, &target_oldset,
+                                        &set, &oldset);
+            if (!is_error(ret)) {
+                target_to_abi_ulong_old_sigset(&mask, &target_oldset);
+#else
             ret = do_sigprocmask(how, &set, &oldset);
             if (!is_error(ret)) {
                 host_to_target_old_sigset(&mask, &oldset);
+#endif
                 ret = mask;
                 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
             }
 #else
             sigset_t set, oldset, *set_ptr;
+#ifdef TRACK_TARGET_SIGMASK
+            target_sigset_t target_set, target_oldset, *target_set_ptr;
+#endif
             int how;
 
             if (arg2) {
@@ -8662,17 +8703,32 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
                     goto efault;
                 target_to_host_old_sigset(&set, p);
+#ifdef TRACK_TARGET_SIGMASK
+                abi_ulong_to_target_old_sigset(&target_set, p);
+                target_set_ptr = &target_set;
+#endif
                 unlock_user(p, arg2, 0);
                 set_ptr = &set;
             } else {
                 how = 0;
                 set_ptr = NULL;
+#ifdef TRACK_TARGET_SIGMASK
+                target_set_ptr = NULL;
+            }
+            ret = do_target_sigprocmask(how, target_set_ptr, &target_oldset,
+                                        set_ptr, &oldset);
+#else
             }
             ret = do_sigprocmask(how, set_ptr, &oldset);
+#endif
             if (!is_error(ret) && arg3) {
                 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
                     goto efault;
+#ifdef TRACK_TARGET_SIGMASK
+                target_to_abi_ulong_old_sigset(p, &target_oldset);
+#else
                 host_to_target_old_sigset(p, &oldset);
+#endif
                 unlock_user(p, arg3, sizeof(target_sigset_t));
             }
 #endif
@@ -8683,6 +8739,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         {
             int how = arg1;
             sigset_t set, oldset, *set_ptr;
+#ifdef TRACK_TARGET_SIGMASK
+            target_sigset_t target_set, target_oldset, *target_set_ptr;
+#endif
 
             if (arg4 != sizeof(target_sigset_t)) {
                 ret = -TARGET_EINVAL;
@@ -8707,17 +8766,32 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
                 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
                     goto efault;
                 target_to_host_sigset(&set, p);
+#ifdef TRACK_TARGET_SIGMASK
+                tswapal_target_sigset(&target_set, p);
+                target_set_ptr = &target_set;
+#endif
                 unlock_user(p, arg2, 0);
                 set_ptr = &set;
             } else {
                 how = 0;
                 set_ptr = NULL;
+#ifdef TRACK_TARGET_SIGMASK
+                target_set_ptr = NULL;
+            }
+            ret = do_target_sigprocmask(how, target_set_ptr, &target_oldset,
+                                        set_ptr, &oldset);
+#else
             }
             ret = do_sigprocmask(how, set_ptr, &oldset);
+#endif
             if (!is_error(ret) && arg3) {
                 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
                     goto efault;
+#ifdef TRACK_TARGET_SIGMASK
+                tswapal_target_sigset(p, &target_oldset);
+#else
                 host_to_target_sigset(p, &oldset);
+#endif
                 unlock_user(p, arg3, sizeof(target_sigset_t));
             }
         }
@@ -8766,10 +8840,16 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #if defined(TARGET_ALPHA)
             abi_ulong mask = arg1;
             target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
+#ifdef TRACK_TARGET_SIGMASK
+            abi_ulong_to_target_old_sigset(&ts->target_sigsuspend_mask, &mask);
+#endif
 #else
             if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
                 goto efault;
             target_to_host_old_sigset(&ts->sigsuspend_mask, p);
+#ifdef TRACK_TARGET_SIGMASK
+            abi_ulong_to_target_old_sigset(&ts->target_sigsuspend_mask, p);
+#endif
             unlock_user(p, arg1, 0);
 #endif
             ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
@@ -8791,6 +8871,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
                 goto efault;
             target_to_host_sigset(&ts->sigsuspend_mask, p);
+#ifdef TRACK_TARGET_SIGMASK
+            tswapal_target_sigset(&ts->target_sigsuspend_mask, p);
+#endif
             unlock_user(p, arg1, 0);
             ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
                                                SIGSET_T_SIZE));
@@ -11030,6 +11113,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             abi_ulong mask;
             int how;
             sigset_t set, oldset;
+#ifdef TRACK_TARGET_SIGMASK
+            target_sigset_t target_set, target_oldset;
+#endif
 
             switch(arg1) {
             case TARGET_SIG_BLOCK:
@@ -11047,9 +11133,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             mask = arg2;
             target_to_host_old_sigset(&set, &mask);
+#ifdef TRACK_TARGET_SIGMASK
+            abi_ulong_to_target_old_sigset(&target_set, &mask);
+            ret = do_target_sigprocmask(how, &target_set, &target_oldset,
+                                        &set, &oldset);
+            if (!ret) {
+                target_to_abi_ulong_old_sigset(&mask, &target_oldset);
+#else
             ret = do_sigprocmask(how, &set, &oldset);
             if (!ret) {
                 host_to_target_old_sigset(&mask, &oldset);
+#endif
                 ret = mask;
             }
         }
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 15/16] [RFC] linux-user: add support for multiplexing larger target signals
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (13 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 14/16] [RFC] linux-user: add functionality for tracking " Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 16/16] [RFC] linux-user: add support for multiplexing signals in rt_sigqueueinfo(), rt_tgsigqueueinfo(), kill() and tgkill() syscalls Miloš Stojanović
  2017-06-02 12:59 ` [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Peter Maydell
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Add MUX_SIG as a multiplex signal number for all target signals which are
out of the host range. Add support for multiplexing in do_sigaction(),
process_pending_signals(), target_set_sigmask() and do_target_sigprocmask().

This patch solves the problem of unusable target signals which are out of
the host range. This is done by enabling the usage of one of the host
signals (MUX_SIG) as a multiplex for all the target signals that are out
of range. In order to have the target signal masks available
TRACK_TARGET_MASK is defined which enables the tracking of the target
signals masks.

The table of signal handlers already supports the whole range of target
signals. In the do_sigaction() function the signal number of signals which
are out of range are replaced by MUX_SIG which bypasses the error from the
host system and doesn't interfere with signal handling on the target.
Since the MUX_SIG is used as a multiplex, it must never be blocked on host,
so support for emulating the blocking of this signal is added. This is done
by only blocking MUX_SIG in the target mask and retrieving its status from
there when it's needed.

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/signal.c       | 32 ++++++++++++++++++++++++++++++++
 linux-user/syscall_defs.h | 20 ++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 006b45b..ceaccab 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -308,6 +308,15 @@ int do_target_sigprocmask(int how, const target_sigset_t *target_set,
     }
     if (oldset) {
         *oldset = ts->signal_mask;
+#ifdef MUX_SIG
+        /*
+         * The emulation of MUX_SIG being blocked is done using the
+         * target_signal_mask, so the status of MUX_SIG is taken from there.
+         */
+        if (target_sigismember(&ts->target_signal_mask, MUX_SIG) == 1) {
+            sigaddset(oldset, MUX_SIG);
+        }
+#endif
     }
 
     if (target_set && set) {
@@ -348,6 +357,15 @@ int do_target_sigprocmask(int how, const target_sigset_t *target_set,
         target_sigdelset(&ts->target_signal_mask, SIGSTOP);
         sigdelset(&ts->signal_mask, SIGKILL);
         sigdelset(&ts->signal_mask, SIGSTOP);
+#ifdef MUX_SIG
+        /*
+         * Since MUX_SIG is used for all the target signals out of the host
+         * range it must never be blocked on host. The emulation of MUX_SIG
+         * being blocked is done using the target_signal_mask. The status
+         * of MUX_SIG is taken form the target_signal_mask.
+         */
+        sigdelset(&ts->signal_mask, MUX_SIG);
+#endif
     }
     return 0;
 }
@@ -373,6 +391,10 @@ static void target_set_sigmask(const sigset_t *set,
 
     ts->signal_mask = *set;
     ts->target_signal_mask = *target_set;
+#ifdef MUX_SIG
+    /* MUX_SIG can't be blocked on host */
+    sigdelset(&ts->signal_mask, MUX_SIG);
+#endif
 }
 #endif
 #endif
@@ -909,6 +931,12 @@ int do_sigaction(int sig, const struct target_sigaction *act,
 
         /* we update the host linux signal state */
         host_sig = target_to_host_signal(sig);
+#ifdef MUX_SIG
+        /* put the out of host range signal into the multiplex */
+        if (sig >= _NSIG && sig < TARGET_NSIG) {
+            host_sig = MUX_SIG;
+        }
+#endif
         if (host_sig != SIGSEGV && host_sig != SIGBUS) {
             sigfillset(&act1.sa_mask);
             act1.sa_flags = SA_SIGINFO;
@@ -6842,6 +6870,10 @@ void process_pending_signals(CPUArchState *cpu_env)
         set = ts->signal_mask;
         sigdelset(&set, SIGSEGV);
         sigdelset(&set, SIGBUS);
+#ifdef MUX_SIG
+        /* MUX_SIG can't be blocked on host */
+        sigdelset(&ts->signal_mask, MUX_SIG);
+#endif
         sigprocmask(SIG_SETMASK, &set, 0);
     }
     ts->in_sigsuspend = 0;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 7eec420..42089fc 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -394,6 +394,26 @@ struct target_dirent64 {
 #define TARGET_NSIG_BPW	   TARGET_ABI_BITS
 #define TARGET_NSIG_WORDS  (TARGET_NSIG / TARGET_NSIG_BPW)
 
+#if _NSIG <= TARGET_NSIG
+/*
+ * MUX_SIG is used as a multiplex signal number - signals that are
+ * out of the host range and in the target range are sent through it.
+ * It is defined as the maximal available real-time signal in order to
+ * comply with the rule that low-numbered signals have highest priority.
+ * (signals using it will have the same priority but it will be smaller
+ * than all the other real-time signals)
+ * SIGRMTAX is avoided so it doesn't interfere with the hack of reversing
+ * __SIGRTMIN and __SIGRTMAX in the host_to_target_signal_table.
+ */
+#define MUX_SIG     (SIGRTMAX - 1)
+
+/*
+ * The target signal masks must be tracked since they are larger than
+ * the host signal masks.
+ */
+#define TRACK_TARGET_SIGMASK
+#endif
+
 typedef struct {
     abi_ulong sig[TARGET_NSIG_WORDS];
 } target_sigset_t;
-- 
1.9.1

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

* [Qemu-devel] [PATCH v2 16/16] [RFC] linux-user: add support for multiplexing signals in rt_sigqueueinfo(), rt_tgsigqueueinfo(), kill() and tgkill() syscalls.
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (14 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 15/16] [RFC] linux-user: add support for multiplexing larger target signals Miloš Stojanović
@ 2017-05-15 14:59 ` Miloš Stojanović
  2017-06-02 12:59 ` [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Peter Maydell
  16 siblings, 0 replies; 21+ messages in thread
From: Miloš Stojanović @ 2017-05-15 14:59 UTC (permalink / raw)
  To: qemu-devel, riku.voipio
  Cc: laurent, Miodrag.Dinic, Aleksandar.Markovic, Petar.Jovanovic,
	yongbok.kim, Milos.Stojanovic

Add support for multiplexing in the host_signal_handler() function and in
system calls rt_sigqueueinfo()/rt_tgsigqueueinfo(), tgkill(), kill() for
the case when pid > 0.

The rt_sigqueueinfo()/rt_tgsigqueueinfo() system calls multiplex target
signals which are out of the host range by setting the si_errno value to
the actual value of the signal and sending the signal to the MUX_SIG
signal number. The host_signal_handler() will pull out the multiplexed
signals and set their signal number to the correct value. That value
should be in the si_errno field of the siginfo_t structure. The si_errno
field is used here but this implementation can be replaced with any other
unused field in the uinfo structure.

The emulation of larger target signal range is done by spoofing the system
call info, adding the signal number to the si_errno field, and sending it
to the host multiplex queue via rt_sigqueueinfo()/rt_tgsigqueueinfo().
In order to send a signal using rt_sigqueueinfo()/rt_tgsigqueueinfo() with
si_code SI_USER or SI_TKILL to another thread or process, we need to
disguise it as some other signal from the kernel range because the host
kernel doesn't allow direct impersonations of those signals. This is done
with SIG_SPOOF which moves the si_code to the nearest unused kernel si_code
value. After the signal is successfully sent the host_signal_handler() of
the receiving thread/process will turn it back into the proper kill/tgkill
signal, before it gets processed.

The tkill() system call as well as kill() with the argument pid <= 0
couldn't be implemented simply using this method because it requires
acquiring information about, and sending simultaneous signals to multiple
threads or processes. These functionalities are out of the scope of
rt_sigqueueinfo()/rt_tgsigqueueinfo().

Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>
---
 linux-user/signal.c       | 22 +++++++++++++
 linux-user/syscall.c      | 81 +++++++++++++++++++++++++++++++++++++++++++++++
 linux-user/syscall_defs.h |  8 +++++
 3 files changed, 111 insertions(+)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index ceaccab..f80a462 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -787,6 +787,28 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
     sig = host_to_target_signal(host_signum);
     if (sig < 1 || sig > TARGET_NSIG)
         return;
+
+#ifdef MUX_SIG
+    if (sig == MUX_SIG) {
+        /* return the spoofed kill/tgkill signals into standard form */
+        if (info->si_code == SIG_SPOOF(SI_USER)) {
+            info->si_code = SI_USER;
+        } else if (info->si_code == SIG_SPOOF(SI_TKILL)) {
+            info->si_code = SI_TKILL;
+        }
+
+        /*
+         * We assume that si_errno field will remain intact during signal
+         * processing on the host. If it changes, the signal will be sent to
+         * the wrong number (most likely to MUX_SIG).
+         */
+        /* get the actual target signal number */
+        int target_sig = info->si_errno;
+        if (target_sig >= _NSIG && target_sig < TARGET_NSIG) {
+            sig = target_sig;
+        }
+    }
+#endif
     trace_user_host_signal(env, host_signum, sig);
 
     rewind_if_in_safe_syscall(puc);
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index f4ce6a8..8190575 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -7123,6 +7123,24 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
     return 0;
 }
 
+#ifdef MUX_SIG
+static inline int multiplex(abi_long *arg, siginfo_t *uinfo)
+{
+    if (*arg >= _NSIG && *arg < TARGET_NSIG) {
+        /*
+         * Using si_errno to transfer the signal number assumes that the field
+         * doesn't change its value before it gets handled in the
+         * host_signal_handler().
+         */
+        uinfo->si_errno = *arg;
+        *arg = MUX_SIG;
+        uinfo->si_signo = MUX_SIG;
+    }
+
+    return 0;
+}
+#endif
+
 /* ??? Using host futex calls even when target atomic operations
    are not really atomic probably breaks things.  However implementing
    futexes locally would make futexes shared between multiple processes
@@ -8258,7 +8276,42 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
         break;
 #endif
     case TARGET_NR_kill:
+#ifdef MUX_SIG
+        if (arg2 >= _NSIG && arg2 < TARGET_NSIG) {
+            siginfo_t info;
+
+            info.si_errno = arg2;
+            info.si_signo = MUX_SIG;
+            info.si_code = SIG_SPOOF(SI_USER);
+            info.si_pid = getpid();
+            info.si_uid = getuid();
+
+            /* pid > 0 */
+            if (arg1 > 0) {
+                ret = get_errno(sys_rt_sigqueueinfo(arg1, MUX_SIG, &info));
+            } else {
+                ret = -TARGET_EINVAL;
+            }
+            /*
+             * TODO: In order to implement kill with rt_tgsigqueueinfo() for
+             * cases where pid <= 0 one needs to get a list of all the relevant
+             * processes and simultaniously send the signal to them.
+             * Missing:
+             * (pid = 0):
+             *     send to every process in the process group of
+             *     the calling process
+             * (pid = -1):
+             *     send to every process for which the calling process
+             *     has permission to send signals, except for process 1 (init)
+             * (pid < -1):
+             *     send to every process in the process group whose ID is -pid
+             */
+        } else {
+            ret = get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
+        }
+#else
         ret = get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
+#endif
         break;
 #ifdef TARGET_NR_rename
     case TARGET_NR_rename:
@@ -8929,6 +8982,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             target_to_host_siginfo(&uinfo, p);
             unlock_user(p, arg3, 0);
+#ifdef MUX_SIG
+            multiplex(&arg2, &uinfo);
+#endif
             ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
         }
         break;
@@ -8942,6 +8998,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
             }
             target_to_host_siginfo(&uinfo, p);
             unlock_user(p, arg4, 0);
+#ifdef MUX_SIG
+            multiplex(&arg3, &uinfo);
+#endif
             ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
         }
         break;
@@ -11743,12 +11802,34 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
 #endif
 
     case TARGET_NR_tkill:
+        /*
+         * TODO: In order to implement tkill with rt_sigqueueinfo() one needs
+         * to get a list of all the threads with the specifiend tid and
+         * simultaniously send the signal to them.
+         */
         ret = get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
         break;
 
     case TARGET_NR_tgkill:
+#ifdef MUX_SIG
+        if (arg3 >= _NSIG && arg3 < TARGET_NSIG) {
+            siginfo_t info;
+
+            info.si_errno = arg3;
+            info.si_signo = MUX_SIG;
+            info.si_code = SIG_SPOOF(SI_TKILL);
+            info.si_pid = getpid();
+            info.si_uid = getuid();
+
+            ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, MUX_SIG, &info));
+        } else {
+            ret = get_errno(safe_tgkill((int)arg1, (int)arg2,
+                            target_to_host_signal(arg3)));
+        }
+#else
         ret = get_errno(safe_tgkill((int)arg1, (int)arg2,
                         target_to_host_signal(arg3)));
+#endif
         break;
 
 #ifdef TARGET_NR_set_robust_list
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 42089fc..16cab53 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -412,6 +412,14 @@ struct target_dirent64 {
  * the host signal masks.
  */
 #define TRACK_TARGET_SIGMASK
+
+/*
+ * This macro is used to change a kill/tgkill signal so it can be sent through
+ * rt_sigqueueinfo()/rt_tgsigqueueinfo(), since the host kernel doesn't allow
+ * direct impersonations of those signals. Subtracting 8 from the code moves
+ * it to the nearest unused kernel si_code value.
+ */
+#define SIG_SPOOF(code)  ((code) - 8)
 #endif
 
 typedef struct {
-- 
1.9.1

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

* Re: [Qemu-devel] [PATCH v2 01/16] linux-user: add strace for getuid(), gettid(), getppid(), geteuid()
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 01/16] linux-user: add strace for getuid(), gettid(), getppid(), geteuid() Miloš Stojanović
@ 2017-05-15 23:33   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-15 23:33 UTC (permalink / raw)
  To: Miloš Stojanović, qemu-devel, riku.voipio
  Cc: Miodrag.Dinic, laurent, Petar.Jovanovic, Aleksandar.Markovic,
	yongbok.kim

On 05/15/2017 11:59 AM, Miloš Stojanović wrote:
> Improve strace support for syscalls getuid(), gettid(), getppid()
> and geteuid(). Since these system calls don't have arguments, "%s()"
> is added in the corresponding strace.list entry so that no arguments
> are printed.
>
> getuid:
> Prior to this commit, typical strace output used to look like this:
> 4894 getuid(4894,0,0,274886293296,-3689348814741910323,4832615904) = 1000
> After this commit, it looks like this:
> 4894 getuid() = 1000
>
> gettid:
> Prior to this commit, typical strace output used to look like this:
> 8307 gettid(0,0,64,0,4832630528,4832615840) = 8307
> After this commit, it looks like this:
> 8307 gettid() = 8307
>
> getppid:
> Prior to this commit, typical strace output used to look like this:
> 20588 getppid(20588,64,0,4832630528,4832615888,0) = 20625
> After this commit, it looks like this:
> 20588 getppid() = 20625
>
> geteuid:
> Prior to this commit, typical strace output used to look like this:
> 20588 geteuid(64,0,0,4832615888,0,-9151031864016699136) = 1000
> After this commit, it looks like this:
> 20588 geteuid() = 1000
>
> Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>

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

> ---
>  linux-user/strace.list | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/linux-user/strace.list b/linux-user/strace.list
> index 3b1282e..6e33788 100644
> --- a/linux-user/strace.list
> +++ b/linux-user/strace.list
> @@ -290,7 +290,7 @@
>  { TARGET_NR_getegid32, "getegid32" , NULL, NULL, NULL },
>  #endif
>  #ifdef TARGET_NR_geteuid
> -{ TARGET_NR_geteuid, "geteuid" , NULL, NULL, NULL },
> +{ TARGET_NR_geteuid, "geteuid" , "%s()", NULL, NULL },
>  #endif
>  #ifdef TARGET_NR_geteuid32
>  { TARGET_NR_geteuid32, "geteuid32" , NULL, NULL, NULL },
> @@ -338,7 +338,7 @@
>  { TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL },
>  #endif
>  #ifdef TARGET_NR_getppid
> -{ TARGET_NR_getppid, "getppid" , NULL, NULL, NULL },
> +{ TARGET_NR_getppid, "getppid" , "%s()", NULL, NULL },
>  #endif
>  #ifdef TARGET_NR_getpriority
>  { TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
> @@ -381,13 +381,13 @@
>    NULL, NULL },
>  #endif
>  #ifdef TARGET_NR_gettid
> -{ TARGET_NR_gettid, "gettid" , NULL, NULL, NULL },
> +{ TARGET_NR_gettid, "gettid" , "%s()", NULL, NULL },
>  #endif
>  #ifdef TARGET_NR_gettimeofday
>  { TARGET_NR_gettimeofday, "gettimeofday" , NULL, NULL, NULL },
>  #endif
>  #ifdef TARGET_NR_getuid
> -{ TARGET_NR_getuid, "getuid" , NULL, NULL, NULL },
> +{ TARGET_NR_getuid, "getuid" , "%s()", NULL, NULL },
>  #endif
>  #ifdef TARGET_NR_getuid32
>  { TARGET_NR_getuid32, "getuid32" , NULL, NULL, NULL },
>

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

* Re: [Qemu-devel] [PATCH v2 05/16] linux-user: fix argument type declaration of rt_sigqueinfo() syscall
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 05/16] linux-user: fix argument type declaration of " Miloš Stojanović
@ 2017-05-15 23:35   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 21+ messages in thread
From: Philippe Mathieu-Daudé @ 2017-05-15 23:35 UTC (permalink / raw)
  To: Miloš Stojanović, qemu-devel, riku.voipio
  Cc: Miodrag.Dinic, laurent, Petar.Jovanovic, Aleksandar.Markovic,
	yongbok.kim

On 05/15/2017 11:59 AM, Miloš Stojanović wrote:
> Change the type of the first argument of rt_sigqueinfo() from int to pid_t
> in the syscall declaration to match specifications of the system call.
>
> Proper spacing is added to satisfy checkpatch.pl.
>
> Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>

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

> ---
>  linux-user/syscall.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index ff03e1a..9ec7ccd 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -274,7 +274,7 @@ _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, co
>  _syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo,
>            loff_t *, res, uint, wh);
>  #endif
> -_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
> +_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
>  _syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
>  #ifdef __NR_exit_group
>  _syscall1(int,exit_group,int,error_code)
>

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

* Re: [Qemu-devel] [PATCH v2 02/16] linux-user: add tkill(), tgkill() and rt_sigqueueinfo() strace
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 02/16] linux-user: add tkill(), tgkill() and rt_sigqueueinfo() strace Miloš Stojanović
@ 2017-06-02 12:31   ` Peter Maydell
  0 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2017-06-02 12:31 UTC (permalink / raw)
  To: Miloš Stojanović
  Cc: QEMU Developers, Riku Voipio, Miodrag.Dinic, Laurent Vivier,
	Petar Jovanovic, Aleksandar Markovic, Yongbok Kim

On 15 May 2017 at 15:59, Miloš Stojanović <Milos.Stojanovic@rt-rk.com> wrote:
> Improve strace support for syscall tkill(), tgkill() and rt_sigqueueinfo()
> by implementing print functions that match arguments types of the system
> calls and add them to the corresponding starce.list entry.
>
> tkill:
> Prior to this commit, typical strace output used to look like this:
> 4886 tkill(4886,50,0,4832615904,0,-9151031864016699136) = 0
> After this commit, it looks like this:
> 4886 tkill(4886,50) = 0
>
> tgkill:
> Prior to this commit, typical strace output used to look like this:
> 4890 tgkill(4890,4890,50,8,4832630528,4832615904) = 0
> After this commit, it looks like this:
> 4890 tgkill(4890,4890,50) = 0
>
> rt_sigqueueinfo:
> Prior to this commit, typical strace output used to look like this:
> 8307 rt_sigqueueinfo(8307,50,1996483164,0,0,50) = 0
> After this commit, it looks like this:
> 8307 rt_sigqueueinfo(8307,50,0x00000040007ff6b0) = 0
>
> Signed-off-by: Miloš Stojanović <Milos.Stojanovic@rt-rk.com>

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

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling
  2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
                   ` (15 preceding siblings ...)
  2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 16/16] [RFC] linux-user: add support for multiplexing signals in rt_sigqueueinfo(), rt_tgsigqueueinfo(), kill() and tgkill() syscalls Miloš Stojanović
@ 2017-06-02 12:59 ` Peter Maydell
  16 siblings, 0 replies; 21+ messages in thread
From: Peter Maydell @ 2017-06-02 12:59 UTC (permalink / raw)
  To: Miloš Stojanović
  Cc: QEMU Developers, Riku Voipio, Miodrag.Dinic, Laurent Vivier,
	Petar Jovanovic, Aleksandar Markovic, Yongbok Kim

On 15 May 2017 at 15:59, Miloš Stojanović <Milos.Stojanovic@rt-rk.com> wrote:
> D. Add support for larger target signal range (RFC patches 10-16):
>
>    Add target signal mask tracking and multiplexing of target signals out
>    of the host range. The patches are marked as RFC because they introduce
>    significant new functionalities regarding signal handling in QEMU.
>
>    Currently, QEMU has a copy of the host signal and suspend masks and
>    that is usually enough, since most of the time the signal mask of the
>    target architecture is either the same length or narrower. If however
>    the signal mask is wider, then part of it won't be tracked. The signals
>    that are in the target range but out of the host range were treated like
>    faulty signals and couldn't be used. This problem is solved by enabling
>    the usage of one of the host signals as a multiplex for all the target
>    signals that are out of range. In order to have the target signal masks
>    available, tracking of target signal masks is implemented.
>
>    The rt_sigqueueinfo()/rt_tgsigqueueinfo() system calls multiplex target
>    signals by setting the si_errno value to the actual value of the signal
>    and sending the signal to a predefined host signal number.
>    The host_signal_handler() will pull out the multiplexed signals and set
>    their signal number to the correct value. The si_errno field is used
>    here but this implementation can be replaced with any other unused field
>    in the uinfo structure. Using this implementation both rt_sigqueueinfo(),
>    rt_tgsigqueueinfo(), as well as kill() (for pid > 0) and tgkill() can be
>    emulated.
>
>    The tkill() system call and kill() with the argument pid <= 0 couldn't
>    be implemented simply using this method because it requires acquiring
>    information about, and sending simultaneous signals to multiple threads
>    or processes. These functionalities are out of the scope of
>    rt_sigqueueinfo()/rt_tgsigqueueinfo().

This certainly sounds good -- can it fix our problems with clashes
between the host libc and guest libc use of signals?

I do wonder if this is opening up subtle bugs, though: if the
guest does:
  * block signal X
  * some syscall
  * unblock X

then we shouldn't interrupt the syscall if signal X arrives.
That works when we use host signal X for guest signal X because
we just block host signal X. But I don't see how it works if X
has to be multiplexed.

As an implementation point: I see you've implemented this with
ifdefs. I think that if we're going to do it we should do it
always, because it's always the case that there are guest signals
that we can't directly represent with host signals, because of
the host libc stealing a couple for its internal use, so we always
need to multiplex at least a few signals. It also makes it easier
to reason about and test if everything is using the same code paths.

thanks
-- PMM

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

end of thread, other threads:[~2017-06-02 13:00 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-15 14:59 [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 01/16] linux-user: add strace for getuid(), gettid(), getppid(), geteuid() Miloš Stojanović
2017-05-15 23:33   ` Philippe Mathieu-Daudé
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 02/16] linux-user: add tkill(), tgkill() and rt_sigqueueinfo() strace Miloš Stojanović
2017-06-02 12:31   ` Peter Maydell
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 03/16] linux-user: fix ssetmask() system call Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 04/16] linux-user: fix mismatch of lock/unlock_user() invocations in rt_sigqueinfo() syscall Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 05/16] linux-user: fix argument type declaration of " Miloš Stojanović
2017-05-15 23:35   ` Philippe Mathieu-Daudé
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 06/16] linux-user: add support for rt_tgsigqueueinfo() system call Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 07/16] linux-user: add rt_tgsigqueueinfo() strace Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 08/16] linux-user: fix inconsistent spaces in print_siginfo() output Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 09/16] linux-user: add strace support for uinfo structure of rt_sigqueueinfo() and rt_tgsigqueueinfo() Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 10/16] [RFC] linux-user: add support for tracking the target signal mask Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 11/16] [RFC] linux-user: add target_sigdelset() and target_sigorset() Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 12/16] [RFC] linux-user: fix sigismember() check Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 13/16] [RFC] linux-user: add functions for working with the target signal mask Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 14/16] [RFC] linux-user: add functionality for tracking " Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 15/16] [RFC] linux-user: add support for multiplexing larger target signals Miloš Stojanović
2017-05-15 14:59 ` [Qemu-devel] [PATCH v2 16/16] [RFC] linux-user: add support for multiplexing signals in rt_sigqueueinfo(), rt_tgsigqueueinfo(), kill() and tgkill() syscalls Miloš Stojanović
2017-06-02 12:59 ` [Qemu-devel] [PATCH v2 00/16] Augment support for signal handling Peter Maydell

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.