[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