summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorleedagee <leedageea@gmail.com>2023-04-29 08:00:00 +0000
committerDmitry V. Levin <ldv@strace.io>2023-04-29 08:00:00 +0000
commit50111982e27976c3dfa3e3411281b88d778f49d5 (patch)
treeec5898c380412863c830c674861531407bf327e1
parent551870dc5cc2421bd960bb42fb25d5027af67efc (diff)
downloadstrace-50111982e27976c3dfa3e3411281b88d778f49d5.tar.gz
Implement decoding of signal masks associated with signalfd file descriptors
When signalfds are used, normal signal handling method is usually disabled, leaving strace without signals to catch and decode. This patch adds decoding of signal masks associated with signalfd file descriptors. Decoding the signalfd_siginfo struct requires additional work mentioned in github#199. Signed-off-by: leedagee <leedageea@gmail.com> * NEWS: Mention this change. * doc/strace.1.in: Document --decode-fds=signalfd. * src/strace.c (usage): Likewise. * src/number_set.h (enum decode_fd_bits): Add DECODE_FD_SIGNALFD. * src/filter_qualify.c (decode_fd_str_to_uint): Handle signalfd. * src/util.c (print_fdinfo_sigmask, printsignalfd): New functions. (printfd_pid_with_finfo): Use printsignalfd when DECODE_FD_SIGNALFD is set in decode_fd_set. * tests/signalfd4.c [PRINT_SIGNALFD]: Check decoding of signal masks associated with signalfd file descriptors. * tests/signalfd4-yy.c: New file. * tests/pure_executables.list: Add signalfd4-yy. * tests/.gitignore: Likewise. * tests/gen_tests.in (signalfd4): Add -a32. (signalfd4-yy): New test. Co-authored-by: Dmitry V. Levin <ldv@strace.io>
-rw-r--r--NEWS2
-rw-r--r--doc/strace.1.in5
-rw-r--r--src/filter_qualify.c1
-rw-r--r--src/number_set.h1
-rw-r--r--src/strace.c3
-rw-r--r--src/util.c44
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/gen_tests.in3
-rwxr-xr-xtests/pure_executables.list1
-rw-r--r--tests/signalfd4-yy.c4
-rw-r--r--tests/signalfd4.c35
11 files changed, 93 insertions, 7 deletions
diff --git a/NEWS b/NEWS
index c7798adf0..c82e6c895 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,8 @@ Noteworthy changes in release ?.? (????-??-??)
==============================================
* Improvements
+ * Implemented --decode-fds=signalfd option for decoding of signal masks
+ associated with signalfd file descriptors.
* Implemented -e trace-fds=set option for filtering only the syscalls
that operate on the specified set of file descriptors.
* Implemented -l/--syscall-limit option to automatically detach tracees
diff --git a/doc/strace.1.in b/doc/strace.1.in
index 16a94fc7d..8a8137bad 100644
--- a/doc/strace.1.in
+++ b/doc/strace.1.in
@@ -919,7 +919,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
@@ -934,6 +934,9 @@ Print character/block device numbers.
.TQ
.B pidfd
Print PIDs associated with pidfd file descriptors.
+.TQ
+.B signalfd
+Print signal masks associated with signalfd file descriptors.
.RE
.TP
\fB\-e\ decode\-pids\fR=\,\fIset\fR
diff --git a/src/filter_qualify.c b/src/filter_qualify.c
index 3aa9f2a19..9d23b6a11 100644
--- a/src/filter_qualify.c
+++ b/src/filter_qualify.c
@@ -106,6 +106,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 639d4c256..2458fdef7 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 0f34e8961..7caa6d9ec 100644
--- a/src/strace.c
+++ b/src/strace.c
@@ -369,7 +369,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 masks for signalfds)\n\
"
#ifdef ENABLE_SECONTEXT
"\
diff --git a/src/util.c b/src/util.c
index e43e4b725..343cf8850 100644
--- a/src/util.c
+++ b/src/util.c
@@ -790,6 +790,47 @@ printpidfd(pid_t pid_of_fd, int fd, const char *path)
return true;
}
+static bool
+print_fdinfo_sigmask(const char *value, void *data)
+{
+#ifdef WORDS_BIGENDIAN
+ unsigned int pos_xor_mask = current_wordsize - 1;
+#else
+ unsigned int pos_xor_mask = 0;
+#endif
+ size_t sigset_size = strlen(value) / 2;
+ uint8_t *sigmask = xmalloc(sigset_size);
+
+ for (size_t i = 0; i < sigset_size; ++i) {
+ uint8_t byte;
+ if (sscanf(value + i * 2, "%02hhx", &byte) != 1) {
+ free(sigmask);
+ return false;
+ }
+ sigmask[(sigset_size - 1 - i) ^ pos_xor_mask] = byte;
+ }
+
+ tprint_associated_info_begin();
+ tprints_string(sprintsigmask_n("signalfd:", sigmask, sigset_size));
+ tprint_associated_info_end();
+
+ free(sigmask);
+ return true;
+}
+
+static bool
+printsignalfd(pid_t pid_of_fd, 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;
+
+ return scan_fdinfo(pid_of_fd, fd, sigmask_pfx, sizeof(sigmask_pfx) - 1,
+ print_fdinfo_sigmask, NULL);
+}
+
static void
print_quoted_string_in_angle_brackets(const char *str, const bool deleted)
{
@@ -821,6 +862,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 4c753e324..d0f99f01e 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -982,6 +982,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 1316ad6e8..f19963b06 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -960,7 +960,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 -a32
+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 a1315f64e..4c32d8b99 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -695,6 +695,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;