[PATCH v2 2/2] decode-fds: add signalfd fdinfo decoding support
leedagee
leedageea at gmail.com
Sun Mar 26 01:39:47 UTC 2023
When signalfds are used, normal signal handling method is not used
causing strace unable to catch these signals and therefore unable to
decode them.
This patch adds a basic a support for signalfd fdinfo decoding.
Decoding the buffer content needs more patch but there's also previous
work by esyr and masatake (see github #199).
Signed-off-by: leedagee <leedageea at gmail.com>
---
NEWS | 1 +
doc/strace.1.in | 5 ++++-
src/filter_qualify.c | 1 +
src/number_set.h | 1 +
src/strace.c | 3 ++-
src/util.c | 44 +++++++++++++++++++++++++++++++++++++
tests/.gitignore | 1 +
tests/gen_tests.in | 3 ++-
tests/pure_executables.list | 1 +
tests/signalfd4-yy.c | 4 ++++
tests/signalfd4.c | 35 +++++++++++++++++++++++++----
11 files changed, 92 insertions(+), 7 deletions(-)
create mode 100644 tests/signalfd4-yy.c
diff --git a/NEWS b/NEWS
index fa56409ba..08bd2fa91 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,7 @@ Noteworthy changes in release ?.? (????-??-??)
==============================================
* Improvements
+ * Implemented decoding of signalfd sigmasks.
Noteworthy changes in release 6.2 (2023-02-26)
==============================================
diff --git a/doc/strace.1.in b/doc/strace.1.in
index 71661bd2e..b41057519 100644
--- a/doc/strace.1.in
+++ b/doc/strace.1.in
@@ -888,7 +888,7 @@ Decode various information associated with file descriptors. The default is
.I set
can include the following elements:
.RS
-.TP 8
+.TP 9
.B path
Print file paths.
Also enables printing of tracee's current working directory when
@@ -903,6 +903,9 @@ Print character/block device numbers.
.TQ
.B pidfd
Print PIDs associated with pidfd file descriptors.
+.TQ
+.B signalfd
+Print signal mask for signalfds.
.RE
.TP
\fB\-e\ decode\-pids\fR=\,\fIset\fR
diff --git a/src/filter_qualify.c b/src/filter_qualify.c
index c3bf2e9ad..c15a68bd3 100644
--- a/src/filter_qualify.c
+++ b/src/filter_qualify.c
@@ -105,6 +105,7 @@ decode_fd_str_to_uint(const char *str)
{ DECODE_FD_SOCKET, "socket" },
{ DECODE_FD_DEV, "dev" },
{ DECODE_FD_PIDFD, "pidfd" },
+ { DECODE_FD_SIGNALFD, "signalfd" },
};
return (int) find_arg_val(str, decode_fd_strs, -1ULL, -1ULL);
diff --git a/src/number_set.h b/src/number_set.h
index 5cd030f7c..d4bfb1405 100644
--- a/src/number_set.h
+++ b/src/number_set.h
@@ -76,6 +76,7 @@ enum decode_fd_bits {
DECODE_FD_SOCKET,
DECODE_FD_DEV,
DECODE_FD_PIDFD,
+ DECODE_FD_SIGNALFD,
NUM_DECODE_FD_BITS
};
diff --git a/src/strace.c b/src/strace.c
index 21b693d02..e5eb93818 100644
--- a/src/strace.c
+++ b/src/strace.c
@@ -365,7 +365,8 @@ Output format:\n\
details: dev (device major/minor for block/char device files)\n\
path (file path),\n\
pidfd (associated PID for pidfds),\n\
- socket (protocol-specific information for socket descriptors)\n\
+ socket (protocol-specific information for socket descriptors),\n\
+ signalfd (signal mask for signalfds)\n\
"
#ifdef ENABLE_SECONTEXT
"\
diff --git a/src/util.c b/src/util.c
index f3013ec64..8d333c358 100644
--- a/src/util.c
+++ b/src/util.c
@@ -784,6 +784,47 @@ printpidfd(pid_t pid_of_fd, int fd, const char *path)
return true;
}
+static bool
+printsignalfd(pid_t pid, int fd, const char *path)
+{
+ static const char signalfd_path[] = "anon_inode:[signalfd]";
+ static const char sigmask_pfx[] = "sigmask:\t";
+
+ if (strcmp(path, signalfd_path))
+ return false;
+
+ char *result = search_fdinfo(pid, fd, sigmask_pfx, sizeof(sigmask_pfx) - 1);
+
+ if (result == NULL)
+ return false;
+
+ size_t sigset_size = strlen(result) / 2;
+ char *sigmask = xmalloc(sigset_size);
+
+ for (size_t i = 0; i < sigset_size; i++) {
+ if (sscanf(result + i * 2, "%02hhx", sigmask +
+#ifndef WORDS_BIGENDIAN
+ sigset_size - 1 -
+#endif
+ i) != 1) {
+ free(sigmask);
+ free(result);
+
+ return false;
+ }
+ }
+
+ free(result);
+
+ tprint_associated_info_begin();
+ tprints_string(sprintsigmask_n("signalfd:", sigmask, sigset_size));
+ tprint_associated_info_end();
+
+ free(sigmask);
+
+ return true;
+}
+
static void
print_quoted_string_in_angle_brackets(const char *str, const bool deleted)
{
@@ -815,6 +856,9 @@ printfd_pid_with_finfo(struct tcb *tcp, pid_t pid, int fd, const struct finfo *f
if (is_number_in_set(DECODE_FD_PIDFD, decode_fd_set) &&
printpidfd(pid, fd, path))
goto printed;
+ if (is_number_in_set(DECODE_FD_SIGNALFD, decode_fd_set) &&
+ printsignalfd(pid, fd, path))
+ goto printed;
if (is_number_in_set(DECODE_FD_PATH, decode_fd_set))
print_quoted_string_in_angle_brackets(path,
finfo? finfo->deleted: deleted);
diff --git a/tests/.gitignore b/tests/.gitignore
index 5935c39d9..3548b8209 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -958,6 +958,7 @@ signal
signal_receive
signal_receive--pidns-translation
signalfd4
+signalfd4-yy
sigpending
sigprocmask
sigreturn
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index eceac8d60..3c4710b0b 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -936,7 +936,8 @@ siginfo -e trace=none
signal -a25 -e signal=none -e trace='/^signal$'
signal_receive -a16 -e trace=kill
signal_receive--pidns-translation test_pidns -a16 -e trace=kill
-signalfd4
+signalfd4 -a10
+signalfd4-yy --trace=signalfd4 -yy
sigpending -a15
sigprocmask -a34
sigreturn -esignal='!USR1'
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index db527ee7b..c9ccdeefb 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -683,6 +683,7 @@ sigaltstack
siginfo
signal
signalfd4
+signalfd4-yy
sigpending
sigprocmask
sigreturn
diff --git a/tests/signalfd4-yy.c b/tests/signalfd4-yy.c
new file mode 100644
index 000000000..6a5262628
--- /dev/null
+++ b/tests/signalfd4-yy.c
@@ -0,0 +1,4 @@
+#define SKIP_IF_PROC_IS_UNAVAILABLE skip_if_unavailable("/proc/self/fd/")
+#define PRINT_SIGNALFD
+
+#include "signalfd4.c"
diff --git a/tests/signalfd4.c b/tests/signalfd4.c
index e45e9425c..97e7977a2 100644
--- a/tests/signalfd4.c
+++ b/tests/signalfd4.c
@@ -20,20 +20,47 @@
# include <sys/signalfd.h>
# include "kernel_fcntl.h"
+#ifndef SKIP_IF_PROC_IS_UNAVAILABLE
+# define SKIP_IF_PROC_IS_UNAVAILABLE
+#endif
+
int
main(void)
{
- const char *const sigs = SIGUSR2 < SIGCHLD ? "USR2 CHLD" : "CHLD USR2";
+ SKIP_IF_PROC_IS_UNAVAILABLE;
+
+ const char *const sigs1 = "USR2";
+ const char *const sigs2 = SIGUSR2 < SIGCHLD ? "USR2 CHLD" : "CHLD USR2";
const unsigned int size = get_sigset_size();
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGUSR2);
+
+ int fd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
+
+#ifdef PRINT_SIGNALFD
+ if (fd == -1)
+ perror_msg_and_skip("signalfd");
+#endif
+
+ printf("signalfd4(-1, [%s], %u, SFD_CLOEXEC|SFD_NONBLOCK) = %s",
+ sigs1, size, sprintrc(fd));
+#ifdef PRINT_SIGNALFD
+ printf("<signalfd:[%s]>\n", sigs1);
+#else
+ putchar('\n');
+#endif
+
sigaddset(&mask, SIGCHLD);
+ fd = signalfd(fd, &mask, 0);
- int fd = signalfd(-1, &mask, O_CLOEXEC | O_NONBLOCK);
- printf("signalfd4(-1, [%s], %u, SFD_CLOEXEC|SFD_NONBLOCK) = %s\n",
- sigs, size, sprintrc(fd));
+#ifdef PRINT_SIGNALFD
+ printf("signalfd4(%d<signalfd:[%s]>, [%s], %u, 0) = %s<signalfd:[%s]>\n",
+ fd, sigs1, sigs2, size, sprintrc(fd), sigs2);
+#else
+ printf("signalfd4(%d, [%s], %u, 0) = %s\n", fd, sigs2, size, sprintrc(fd));
+#endif
puts("+++ exited with 0 +++");
return 0;
--
2.35.3
More information about the Strace-devel
mailing list