diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | doc/strace.1.in | 5 | ||||
-rw-r--r-- | src/filter_qualify.c | 1 | ||||
-rw-r--r-- | src/number_set.h | 1 | ||||
-rw-r--r-- | src/strace.c | 3 | ||||
-rw-r--r-- | src/util.c | 44 | ||||
-rw-r--r-- | tests/.gitignore | 1 | ||||
-rw-r--r-- | tests/gen_tests.in | 3 | ||||
-rwxr-xr-x | tests/pure_executables.list | 1 | ||||
-rw-r--r-- | tests/signalfd4-yy.c | 4 | ||||
-rw-r--r-- | tests/signalfd4.c | 35 |
11 files changed, 93 insertions, 7 deletions
@@ -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; |