* basic_actions (apply_read, apply_write): Add syscall check. * basic_filters (run_fd_filter): Implement more accurate fd filtering. * defs.h (read_dumped, write_dumped): Add new flag checking macroses. * syscall.c (dumpio): And use them. --- basic_actions.c | 30 ++++++++++- basic_filters.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- defs.h | 2 + syscall.c | 4 +- 4 files changed, 191 insertions(+), 8 deletions(-)
diff --git a/basic_actions.c b/basic_actions.c index 1eb597e..bd05832 100644 --- a/basic_actions.c +++ b/basic_actions.c @@ -26,6 +26,7 @@ */ #include "defs.h" #include "filter.h" +#include "syscall.h" bool is_traced(struct tcb *tcp) @@ -131,13 +132,38 @@ void free_inject(void *_priv_data) void apply_read(struct tcb *tcp, void *_priv_data) { - tcp->qual_flg |= QUAL_READ; + switch (tcp->s_ent->sen) { + case SEN_read: + case SEN_pread: + case SEN_recv: + case SEN_recvfrom: + case SEN_mq_timedreceive: + case SEN_readv: + case SEN_preadv: + case SEN_preadv2: + case SEN_recvmsg: + case SEN_recvmmsg: + tcp->qual_flg |= QUAL_READ; + } } void apply_write(struct tcb *tcp, void *_priv_data) { - tcp->qual_flg |= QUAL_WRITE; + switch (tcp->s_ent->sen) { + case SEN_write: + case SEN_pwrite: + case SEN_send: + case SEN_sendto: + case SEN_mq_timedsend: + case SEN_writev: + case SEN_pwritev: + case SEN_pwritev2: + case SEN_vmsplice: + case SEN_sendmsg: + case SEN_sendmmsg: + tcp->qual_flg |= QUAL_WRITE; + } } void diff --git a/basic_filters.c b/basic_filters.c index d0816a4..82f1656 100644 --- a/basic_filters.c +++ b/basic_filters.c @@ -27,6 +27,8 @@ */ #include "defs.h" #include <regex.h> +#include <poll.h> +#include "syscall.h" typedef unsigned int number_slot_t; #define BITS_PER_SLOT (sizeof(number_slot_t) * 8) @@ -412,14 +414,167 @@ parse_fd_filter(const char *str, const char *const name) return set; } +static bool +is_fd_in_set(int fd, struct number_set *set) { + if (fd < 0) + return false; + return is_number_in_set(fd, set); +} + bool run_fd_filter(struct tcb *tcp, void *_priv_data) { - int fd = tcp->u_arg[0]; - if (fd < 0) - return false; struct number_set *set = (struct number_set *)_priv_data; - return is_number_in_set(fd, set); + const struct_sysent *s_ent = tcp->s_ent; + /* + * mq_timedsend and mq_timedreceive are not marked as descriptor + * syscalls, but they can be dumped with -e read/write. + */ + switch (s_ent->sen) { + case SEN_mq_timedsend: + case SEN_mq_timedreceive: + return is_fd_in_set(tcp->u_arg[0], set); + } + if (!(s_ent->sys_flags & (TRACE_DESC | TRACE_NETWORK))) + return false; + switch (s_ent->sen) { + case SEN_dup2: + case SEN_dup3: + case SEN_kexec_file_load: + case SEN_sendfile: + case SEN_sendfile64: + case SEN_tee: + return is_fd_in_set(tcp->u_arg[0], set) + || is_fd_in_set(tcp->u_arg[1], set); + case SEN_linkat: + case SEN_renameat2: + case SEN_renameat: + case SEN_copy_file_range: + case SEN_splice: + return is_fd_in_set(tcp->u_arg[0], set) + || is_fd_in_set(tcp->u_arg[2], set); + + case SEN_old_mmap: +#if defined(S390) + case SEN_old_mmap_pgoff: +#endif + case SEN_mmap: + case SEN_mmap_4koff: + case SEN_mmap_pgoff: + case SEN_ARCH_mmap: + return is_fd_in_set(tcp->u_arg[4], set); + case SEN_symlinkat: + return is_fd_in_set(tcp->u_arg[1], set); + case SEN_epoll_ctl: + return is_fd_in_set(tcp->u_arg[2], set); + case SEN_fanotify_mark: + return is_fd_in_set(tcp->u_arg[3], set); + case SEN_oldselect: + case SEN_pselect6: + case SEN_select: + { + int i, j; + int nfds; + kernel_ulong_t *args; + kernel_ulong_t select_args[5]; + unsigned int oldselect_args[5]; + unsigned int fdsize; + fd_set *fds; + + if (SEN_oldselect == s_ent->sen) { + if (sizeof(*select_args) == sizeof(*oldselect_args)) { + if (umove(tcp, tcp->u_arg[0], &select_args)) { + return false; + } + } else { + unsigned int n; + + if (umove(tcp, tcp->u_arg[0], &oldselect_args)) { + return false; + } + + for (n = 0; n < 5; ++n) { + select_args[n] = oldselect_args[n]; + } + } + args = select_args; + } else { + args = tcp->u_arg; + } + + /* Kernel truncates arg[0] to int, we do the same. */ + nfds = (int) args[0]; + /* Kernel rejects negative nfds, so we don't parse it either. */ + if (nfds <= 0) + return false; + /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ + if (nfds > 1024*1024) + nfds = 1024*1024; + fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize; + fds = xmalloc(fdsize); + + for (i = 1; i <= 3; ++i) { + if (args[i] == 0) + continue; + if (umoven(tcp, args[i], fdsize, fds) < 0) { + continue; + } + for (j = 0;; j++) { + j = next_set_bit(fds, j, nfds); + if (j < 0) + break; + if (is_fd_in_set(j, set)) { + free(fds); + return true; + } + } + } + free(fds); + return false; + } + case SEN_poll: + case SEN_ppoll: + { + struct pollfd fds; + unsigned nfds; + kernel_ulong_t start, cur, end; + + start = tcp->u_arg[0]; + nfds = tcp->u_arg[1]; + + end = start + sizeof(fds) * nfds; + + if (nfds == 0 || end < start) + return false; + + for (cur = start; cur < end; cur += sizeof(fds)) + if ((umove(tcp, cur, &fds) == 0) + && is_fd_in_set(fds.fd, set)) + return true; + + return false; + } + case SEN_bpf: + case SEN_creat: + case SEN_epoll_create: + case SEN_epoll_create1: + case SEN_eventfd2: + case SEN_eventfd: + case SEN_fanotify_init: + case SEN_inotify_init1: + case SEN_memfd_create: + case SEN_open: + case SEN_perf_event_open: + case SEN_pipe: + case SEN_pipe2: + case SEN_printargs: + case SEN_socket: + case SEN_socketpair: + case SEN_timerfd_create: + case SEN_userfaultfd: + return false; + } + return is_fd_in_set(tcp->u_arg[0], set); } void diff --git a/defs.h b/defs.h index 21dec65..4b3516b 100644 --- a/defs.h +++ b/defs.h @@ -283,6 +283,8 @@ struct tcb { #define syserror(tcp) ((tcp)->u_error != 0) #define verbose(tcp) ((tcp)->qual_flg & QUAL_VERBOSE) #define abbrev(tcp) ((tcp)->qual_flg & QUAL_ABBREV) +#define read_dumped(tcp) ((tcp)->qual_flg & QUAL_READ) +#define write_dumped(tcp) ((tcp)->qual_flg & QUAL_WRITE) #define filtered(tcp) ((tcp)->flags & TCB_FILTERED) #define hide_log(tcp) ((tcp)->flags & TCB_HIDE_LOG) diff --git a/syscall.c b/syscall.c index b6e1ba3..c782f99 100644 --- a/syscall.c +++ b/syscall.c @@ -465,7 +465,7 @@ dumpio(struct tcb *tcp) if (fd < 0) return; - if (tcp->qual_flg & QUAL_READ) { + if (read_dumped(tcp)) { switch (tcp->s_ent->sen) { case SEN_read: case SEN_pread: @@ -488,7 +488,7 @@ dumpio(struct tcb *tcp) return; } } - if (tcp->qual_flg & QUAL_WRITE) { + if (write_dumped(tcp)) { switch (tcp->s_ent->sen) { case SEN_write: case SEN_pwrite: -- 2.1.4 ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel