* pathtrace.c (match_fd_common, pathtrace_match_set): Move fd matching to separate function. * filter.h (match_fd_common): Add new declaration. * basic_filters.c (run_fd_filter): Use match_fd_common for fd filter. --- basic_filters.c | 82 ++++++++++++++++++++++- filter.h | 2 + pathtrace.c | 202 ++++++++++++++++++++++++++++++++++++++------------------ 3 files changed, 219 insertions(+), 67 deletions(-)
diff --git a/basic_filters.c b/basic_filters.c index 85eb58b..2761a74 100644 --- a/basic_filters.c +++ b/basic_filters.c @@ -29,6 +29,7 @@ #include "defs.h" #include <regex.h> #include "filter.h" +#include "syscall.h" typedef unsigned int number_slot_t; #define BITS_PER_SLOT (sizeof(number_slot_t) * 8) @@ -414,15 +415,90 @@ parse_fd_filter(const char *str) return set; } +static bool +is_fd_in_set(struct tcb *tcp, int fd, void *data) { + struct number_set *set = data; + + if (fd < 0) + return set->not; + return is_number_in_set(fd, set); +} + bool run_fd_filter(struct tcb *tcp, void *_priv_data) { - int fd = tcp->u_arg[0]; struct number_set *set = _priv_data; + const struct_sysent *s_ent = tcp->s_ent; - if (fd < 0) + /* + * 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, tcp->u_arg[0], set); + } + + if (!(s_ent->sys_flags & (TRACE_DESC | TRACE_NETWORK))) return false; - return is_number_in_set(fd, set); + + if (match_fd_common(tcp, &is_fd_in_set, set)) + return true; + + switch (s_ent->sen) { + /* Already tested with match_fd_common. */ + case SEN_dup2: + case SEN_dup3: + case SEN_kexec_file_load: + case SEN_sendfile: + case SEN_sendfile64: + case SEN_tee: + case SEN_linkat: + case SEN_renameat2: + case SEN_renameat: + case SEN_copy_file_range: + case SEN_splice: + 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: + case SEN_symlinkat: + case SEN_fanotify_mark: + case SEN_oldselect: + case SEN_pselect6: + case SEN_select: + case SEN_poll: + case SEN_ppoll: + /* + * These have TRACE_DESCRIPTOR or TRACE_NETWORK set, + * but they don't have any file descriptor to test. + */ + 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, tcp->u_arg[0], set); } void diff --git a/filter.h b/filter.h index 4085d45..ead8387 100644 --- a/filter.h +++ b/filter.h @@ -39,6 +39,8 @@ void parse_set(const char *const, struct number_set *const, string_to_uint_func, const char *const); void parse_inject_common_args(char *, struct inject_opts *, const char *delim, const bool fault_tokens_only); +typedef bool (*match_fd_func)(struct tcb *, int, void *); +int match_fd_common(struct tcb *, match_fd_func, void *); /* filter api */ struct filter* add_filter_to_array(struct filter **, unsigned int *nfilters, diff --git a/pathtrace.c b/pathtrace.c index 26a52fe..b1e1f08 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -69,6 +69,8 @@ upathmatch(struct tcb *const tcp, const kernel_ulong_t upath, static bool fdmatch(struct tcb *tcp, int fd, struct path_set *set) { + if (fd < 0) + return false; char path[PATH_MAX + 1]; int n = getfdpath(tcp, fd, path, sizeof(path)); @@ -143,36 +145,23 @@ pathtrace_select_set(const char *path, struct path_set *set) storepath(rpath, set); } -/* - * Return true if syscall accesses a selected path - * (or if no paths have been specified for tracing). - */ -bool -pathtrace_match_set(struct tcb *tcp, struct path_set *set) +typedef bool (*match_fd_func)(struct tcb *, int, void *); + +static +bool fdmatch_fd_func(struct tcb *tcp, int fd, void *data) { - const struct_sysent *s; + return fdmatch(tcp, fd, (struct path_set *) data); +} - s = tcp->s_ent; +/* Match fd with func. */ +bool +match_fd_common(struct tcb *tcp, match_fd_func func, void *data) +{ + const struct_sysent *s = tcp->s_ent; - if (!(s->sys_flags & (TRACE_FILE | TRACE_DESC | TRACE_NETWORK))) + if (!(s->sys_flags & (TRACE_DESC | TRACE_NETWORK))) return false; - - /* - * Check for special cases where we need to do something - * other than test arg[0]. - */ - switch (s->sen) { - case SEN_dup2: - case SEN_dup3: - case SEN_kexec_file_load: - case SEN_sendfile: - case SEN_sendfile64: - case SEN_tee: - /* fd, fd */ - return fdmatch(tcp, tcp->u_arg[0], set) || - fdmatch(tcp, tcp->u_arg[1], set); - case SEN_faccessat: case SEN_fchmodat: case SEN_fchownat: @@ -188,29 +177,27 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set) case SEN_statx: case SEN_unlinkat: case SEN_utimensat: - /* fd, path */ - return fdmatch(tcp, tcp->u_arg[0], set) || - upathmatch(tcp, tcp->u_arg[1], set); - - case SEN_link: - case SEN_mount: - case SEN_pivotroot: - /* path, path */ - return upathmatch(tcp, tcp->u_arg[0], set) || - upathmatch(tcp, tcp->u_arg[1], set); + /* fd, path special case */ + return func(tcp, tcp->u_arg[0], data); - case SEN_quotactl: - /* x, path */ - return upathmatch(tcp, tcp->u_arg[1], set); + case SEN_dup2: + case SEN_dup3: + case SEN_kexec_file_load: + case SEN_sendfile: + case SEN_sendfile64: + case SEN_tee: + /* fd, fd */ + return func(tcp, tcp->u_arg[0], data) || + func(tcp, tcp->u_arg[1], data); case SEN_linkat: case SEN_renameat2: case SEN_renameat: - /* fd, path, fd, path */ - return fdmatch(tcp, tcp->u_arg[0], set) || - fdmatch(tcp, tcp->u_arg[2], set) || - upathmatch(tcp, tcp->u_arg[1], set) || - upathmatch(tcp, tcp->u_arg[3], set); + case SEN_copy_file_range: + case SEN_splice: + /* fd, x, fd */ + return func(tcp, tcp->u_arg[0], data) || + func(tcp, tcp->u_arg[2], data); case SEN_old_mmap: #if defined(S390) @@ -221,33 +208,25 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set) case SEN_mmap_pgoff: case SEN_ARCH_mmap: /* x, x, x, x, fd */ - return fdmatch(tcp, tcp->u_arg[4], set); + return func(tcp, tcp->u_arg[4], data); case SEN_symlinkat: - /* path, fd, path */ - return fdmatch(tcp, tcp->u_arg[1], set) || - upathmatch(tcp, tcp->u_arg[0], set) || - upathmatch(tcp, tcp->u_arg[2], set); - - case SEN_copy_file_range: - case SEN_splice: - /* fd, x, fd, x, x, x */ - return fdmatch(tcp, tcp->u_arg[0], set) || - fdmatch(tcp, tcp->u_arg[2], set); + /* x, fd, x */ + return func(tcp, tcp->u_arg[1], data); case SEN_epoll_ctl: /* x, x, fd, x */ - return fdmatch(tcp, tcp->u_arg[2], set); - + return func(tcp, tcp->u_arg[2], data); case SEN_fanotify_mark: { /* x, x, mask (64 bit), fd, path */ unsigned long long mask = 0; int argn = getllval(tcp, &mask, 2); - return fdmatch(tcp, tcp->u_arg[argn], set) || - upathmatch(tcp, tcp->u_arg[argn + 1], set); + + return func(tcp, tcp->u_arg[argn], data); } + case SEN_oldselect: case SEN_pselect6: case SEN_select: @@ -302,7 +281,7 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set) j = next_set_bit(fds, j, nfds); if (j < 0) break; - if (fdmatch(tcp, j, set)) { + if (func(tcp, j, data)) { free(fds); return true; } @@ -329,12 +308,111 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set) for (cur = start; cur < end; cur += sizeof(fds)) if ((umove(tcp, cur, &fds) == 0) - && fdmatch(tcp, fds.fd, set)) + && func(tcp, fds.fd, data)) return true; return false; } + } + return false; +} + +/* + * Return true if syscall accesses a selected path + * (or if no paths have been specified for tracing). + */ +bool +pathtrace_match_set(struct tcb *tcp, struct path_set *set) +{ + const struct_sysent *s; + + s = tcp->s_ent; + + if (!(s->sys_flags & (TRACE_FILE | TRACE_DESC | TRACE_NETWORK))) + return false; + if (match_fd_common(tcp, fdmatch_fd_func, set)) + return true; + + /* + * Check for special cases where we need to do something + * other than test arg[0]. + */ + switch (s->sen) { + case SEN_faccessat: + case SEN_fchmodat: + case SEN_fchownat: + case SEN_fstatat64: + case SEN_futimesat: + case SEN_inotify_add_watch: + case SEN_mkdirat: + case SEN_mknodat: + case SEN_name_to_handle_at: + case SEN_newfstatat: + case SEN_openat: + case SEN_quotactl: + case SEN_readlinkat: + case SEN_statx: + case SEN_unlinkat: + case SEN_utimensat: + /* x, path */ + return upathmatch(tcp, tcp->u_arg[1], set); + + case SEN_link: + case SEN_mount: + case SEN_pivotroot: + /* path, path */ + return upathmatch(tcp, tcp->u_arg[0], set) || + upathmatch(tcp, tcp->u_arg[1], set); + + case SEN_linkat: + case SEN_renameat2: + case SEN_renameat: + /* x, path, x, path */ + return upathmatch(tcp, tcp->u_arg[1], set) || + upathmatch(tcp, tcp->u_arg[3], set); + + case SEN_symlinkat: + /* path, x, path */ + return upathmatch(tcp, tcp->u_arg[0], set) || + upathmatch(tcp, tcp->u_arg[2], set); + + case SEN_fanotify_mark: + { + /* x, x, mask (64 bit), fd, path */ + unsigned long long mask = 0; + int argn = getllval(tcp, &mask, 2); + + return upathmatch(tcp, tcp->u_arg[argn + 1], set); + } + + /* Already tested with match_fd_common. */ + case SEN_dup2: + case SEN_dup3: + case SEN_kexec_file_load: + case SEN_sendfile: + case SEN_sendfile64: + case SEN_tee: + case SEN_copy_file_range: + case SEN_splice: + 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: + case SEN_epoll_ctl: + case SEN_oldselect: + case SEN_pselect6: + case SEN_select: + case SEN_poll: + case SEN_ppoll: + /* + * These have TRACE_FILE or TRACE_DESCRIPTOR or TRACE_NETWORK set, + * but they don't have any file descriptor or path args to test. + */ case SEN_bpf: case SEN_epoll_create: case SEN_epoll_create1: @@ -353,10 +431,6 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set) case SEN_timerfd_gettime: case SEN_timerfd_settime: case SEN_userfaultfd: - /* - * These have TRACE_FILE or TRACE_DESCRIPTOR or TRACE_NETWORK set, - * but they don't have any file descriptor or path args to test. - */ return false; } -- 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