]> granicus.if.org Git - strace/commitdiff
Fix decoding of sgetmask and ssetmask syscalls
authorDmitry V. Levin <ldv@altlinux.org>
Mon, 22 May 2017 10:48:13 +0000 (10:48 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Mon, 22 May 2017 17:33:51 +0000 (17:33 +0000)
Old ssetmask syscall takes an argument and returns a value of type int.
Old sgetmask syscall may return an error.

* signal.c (SYS_FUNC(ssetmask)): Explicitly convert the argument
and return value to unsigned int, print it using sprint_old_sigmask_val.
(SYS_FUNC(sgetmask)): Do not print the mask in case of syserror.
* tests/sxetmask.c: New file.
* tests/gen_tests.in (sxetmask): New entry.
* tests/pure_executables.list: Add sxetmask.
* tests/.gitignore: Likewise.
* NEWS: Mention this fix.

NEWS
signal.c
tests/.gitignore
tests/gen_tests.in
tests/pure_executables.list
tests/sxetmask.c [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index b109d98d8c028d0ec65b6a8bc8f6fd8a22324b10..0bc57c57cac55a71b81944373910b7e45826ad34 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,7 @@ Noteworthy changes in release ?.?? (????-??-??)
   * Fixed the number of arguments and tracing flags of alpha specific syscalls.
   * Fixed decoding of old sigsuspend syscall on alpha, cris, mips, powerpc,
     powerpc64, sh, sh64, sparc, and sparc64.
+  * Fixed decoding of sgetmask and ssetmask syscalls on 64-bit architectures.
   * Fixed decoding of netlink messages received within struct msghdr.
   * Worked around a bug in miscompiled aarch64 kernels leading to the 3rd
     argument of sched_getattr syscall being not quite 32-bit.
index 88856b575902da23dd14b12e7e8f6cb8404b6bb0..a384f1fae89f1adc56cde6e97d8b26e3f97ba69c 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -288,10 +288,11 @@ print_sigset_addr(struct tcb *const tcp, const kernel_ulong_t addr)
 SYS_FUNC(ssetmask)
 {
        if (entering(tcp)) {
-               tprintsigmask_val("", tcp->u_arg[0]);
+               tprint_old_sigmask_val("", (unsigned) tcp->u_arg[0]);
        }
        else if (!syserror(tcp)) {
-               tcp->auxstr = sprintsigmask_val("old mask ", tcp->u_rval);
+               tcp->auxstr = sprint_old_sigmask_val("old mask ",
+                                                    (unsigned) tcp->u_rval);
                return RVAL_HEX | RVAL_STR;
        }
        return 0;
@@ -395,10 +396,11 @@ SYS_FUNC(signal)
 
 SYS_FUNC(sgetmask)
 {
-       if (exiting(tcp)) {
+       if (exiting(tcp) && !syserror(tcp)) {
                tcp->auxstr = sprintsigmask_val("mask ", tcp->u_rval);
+               return RVAL_HEX | RVAL_STR;
        }
-       return RVAL_HEX | RVAL_STR;
+       return 0;
 }
 
 SYS_FUNC(sigsuspend)
index 722b5e030ec683b2cc6df388b86d3efabad12c66..babd949389f7517a9b3ec4f181fd7a055adc1dec 100644 (file)
@@ -340,6 +340,7 @@ statfs
 statfs64
 statx
 swap
+sxetmask
 symlink
 symlinkat
 sync
index 24a2d3f13369f23748f3d5c2011b4b01ab0b2f91..be0a3a237115c5a27fa11bac846053074f4f754f 100644 (file)
@@ -293,6 +293,7 @@ statfs      -a17
 statfs64       -a23
 statx  -a32 -v -P stat.sample -P /dev/full
 swap   -a23 -e trace=swapon,swapoff
+sxetmask       -a11 -e trace=sgetmask,ssetmask
 symlink        -a34
 symlinkat
 sync   -a7
index ca7c6b79068d4413ac23b786147b8c56fb6928f6..cc65614a795eac06542e0c3fd567c9672b68c14d 100755 (executable)
@@ -280,6 +280,7 @@ statfs
 statfs64
 statx
 swap
+sxetmask
 symlink
 symlinkat
 sync
diff --git a/tests/sxetmask.c b/tests/sxetmask.c
new file mode 100644 (file)
index 0000000..1554319
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Check decoding of sgetmask and ssetmask syscalls.
+ *
+ * Copyright (c) 2017 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "tests.h"
+#include <asm/unistd.h>
+
+#if defined __NR_sgetmask && defined __NR_ssetmask
+
+# include <errno.h>
+# include <signal.h>
+# include <stdio.h>
+# include <stdint.h>
+# include <string.h>
+# include <unistd.h>
+
+static long
+k_sgetmask(void)
+{
+       return syscall(__NR_sgetmask);
+}
+
+static long
+k_ssetmask(const kernel_ulong_t arg)
+{
+       return syscall(__NR_ssetmask, arg);
+}
+
+int
+main(void)
+{
+       union {
+               sigset_t libc_mask;
+               unsigned long old_mask;
+       } uset, uget;
+       long rc;
+
+       /*
+        * Block, reset, and raise SIGUSR1.
+        * If a subsequent ssetmask call fails to set the proper mask,
+        * the process will be terminated by SIGUSR1.
+        */
+       sigemptyset(&uset.libc_mask);
+       sigaddset(&uset.libc_mask, SIGUSR1);
+       if (sigprocmask(SIG_SETMASK, &uset.libc_mask, NULL))
+               perror_msg_and_fail("sigprocmask");
+       if (signal(SIGUSR1, SIG_DFL) == SIG_ERR)
+               perror_msg_and_fail("signal");
+       raise(SIGUSR1);
+
+       sigaddset(&uset.libc_mask, SIGUSR2);
+       rc = k_ssetmask((kernel_ulong_t) 0xfacefeed00000000ULL | uset.old_mask);
+       if (rc == -1L) {
+               printf("ssetmask([USR1 USR2]) = %s\n", sprintrc(rc));
+       } else {
+               printf("ssetmask([USR1 USR2]) = %#lx (old mask [USR1])\n", rc);
+               /*
+                * Use a regular sigprocmask call to check the value
+                * returned by the ssetmask call being tested.
+                */
+               if (sigprocmask(SIG_SETMASK, NULL, &uget.libc_mask))
+                       perror_msg_and_fail("sigprocmask");
+               if (uset.old_mask != uget.old_mask)
+                       error_msg_and_fail("sigprocmask returned %#lx"
+                                          " instead of %#lx",
+                                          uget.old_mask, uset.old_mask);
+       }
+
+       rc = k_sgetmask();
+       if (rc == -1L) {
+               printf("sgetmask() = %s\n", sprintrc(rc));
+       } else {
+               printf("sgetmask() = %#lx (mask [USR1 USR2])\n", rc);
+               if (uget.old_mask != (unsigned long) rc)
+                       error_msg_and_fail("sigprocmask returned %#lx",
+                                          uget.old_mask);
+       }
+
+       puts("+++ exited with 0 +++");
+       return 0;
+}
+
+#else
+
+SKIP_MAIN_UNDEFINED("__NR_sgetmask && __NR_ssetmask")
+
+#endif