pathtrace_match_set will be exposed to LuaJIT scripts. * defs.h (npaths_selected): Add a declaration. (tracing_paths): Change macro body to an equivalent but more obvious one (pathtrace_match): New macro. * pathtrace.c (num_selected): Rename to npaths_selected, make non-static. (pathmatch, upathmatch, fdmatch, pathtrace_match): Accept a user-provided set of paths, change return type to bool, rename to... (pathmatch_set, upathmatch_set, fdmatch_set, pathtrace_match_set): ...respectively. --- defs.h | 9 ++- pathtrace.c | 223 ++++++++++++++++++++++++++++++------------------------------ 2 files changed, 117 insertions(+), 115 deletions(-)
diff --git a/defs.h b/defs.h index 52d2f137..42382d8e 100644 --- a/defs.h +++ b/defs.h @@ -336,9 +336,10 @@ extern bool count_wallclock; extern unsigned int qflag; extern bool not_failing_only; extern unsigned int show_fd_path; -/* are we filtering traces based on paths? */ extern const char **paths_selected; -#define tracing_paths (paths_selected != NULL) +extern unsigned npaths_selected; +/* are we filtering traces based on paths? */ +#define tracing_paths (npaths_selected != 0) extern unsigned xflag; extern unsigned followfork; #ifdef USE_LIBUNWIND @@ -465,7 +466,9 @@ extern long getrval2(struct tcb *); extern const char *signame(const int); extern void pathtrace_select(const char *); -extern int pathtrace_match(struct tcb *); +extern bool pathtrace_match_set(struct tcb *, const char **, unsigned int); +#define pathtrace_match(tcp) \ + pathtrace_match_set(tcp, paths_selected, npaths_selected) extern int getfdpath(struct tcb *, int, char *, unsigned); extern unsigned long getfdinode(struct tcb *, int); extern enum sock_proto getfdproto(struct tcb *, int); diff --git a/pathtrace.c b/pathtrace.c index 9cb0ba77..b8b35926 100644 --- a/pathtrace.c +++ b/pathtrace.c @@ -34,64 +34,7 @@ #include "syscall.h" const char **paths_selected; -static unsigned int num_selected; - -/* - * Return true if specified path matches one that we're tracing. - */ -static int -pathmatch(const char *path) -{ - unsigned i; - - for (i = 0; i < num_selected; ++i) { - if (strcmp(path, paths_selected[i]) == 0) - return 1; - } - return 0; -} - -/* - * Return true if specified path (in user-space) matches. - */ -static int -upathmatch(struct tcb *const tcp, const kernel_ulong_t upath) -{ - char path[PATH_MAX + 1]; - - return umovestr(tcp, upath, sizeof(path), path) > 0 && - pathmatch(path); -} - -/* - * Return true if specified fd maps to a path we're tracing. - */ -static int -fdmatch(struct tcb *tcp, int fd) -{ - char path[PATH_MAX + 1]; - int n = getfdpath(tcp, fd, path, sizeof(path)); - - return n >= 0 && pathmatch(path); -} - -/* - * Add a path to the set we're tracing. - * Specifying NULL will delete all paths. - */ -static void -storepath(const char *path) -{ - unsigned i; - - if (pathmatch(path)) - return; /* already in table */ - - i = num_selected++; - paths_selected = xreallocarray(paths_selected, num_selected, - sizeof(paths_selected[0])); - paths_selected[i] = path; -} +unsigned int npaths_selected; /* * Get path associated with fd. @@ -117,44 +60,57 @@ getfdpath(struct tcb *tcp, int fd, char *buf, unsigned bufsize) } /* - * Add a path to the set we're tracing. Also add the canonicalized - * version of the path. Secifying NULL will delete all paths. + * Return true if specified path is in a set. */ -void -pathtrace_select(const char *path) +static bool +pathmatch_set(const char *path, const char **set, unsigned int nset) { - char *rpath; + unsigned i; - storepath(path); + for (i = 0; i < nset; ++i) { + if (strcmp(path, set[i]) == 0) + return true; + } + return false; +} - rpath = realpath(path, NULL); +/* + * Return true if specified path (in user-space) is in a set. + */ +static bool +upathmatch_set(struct tcb *const tcp, const kernel_ulong_t upath, + const char **set, unsigned int nset) +{ + char path[PATH_MAX + 1]; - if (rpath == NULL) - return; + return umovestr(tcp, upath, sizeof(path), path) > 0 && + pathmatch_set(path, set, nset); +} - /* if realpath and specified path are same, we're done */ - if (strcmp(path, rpath) == 0) { - free(rpath); - return; - } +/* + * Return true if specified fd maps to a path in a set. + */ +static bool +fdmatch_set(struct tcb *tcp, int fd, const char **set, unsigned int nset) +{ + char path[PATH_MAX + 1]; + int n = getfdpath(tcp, fd, path, sizeof(path)); - error_msg("Requested path '%s' resolved into '%s'", path, rpath); - storepath(rpath); + return n >= 0 && pathmatch_set(path, set, nset); } /* - * Return true if syscall accesses a selected path - * (or if no paths have been specified for tracing). + * Return true if syscall accesses a path in a set. */ -int -pathtrace_match(struct tcb *tcp) +bool +pathtrace_match_set(struct tcb *tcp, const char **set, unsigned int nset) { const struct_sysent *s; s = tcp->s_ent; if (!(s->sys_flags & (TRACE_FILE | TRACE_DESC | TRACE_NETWORK))) - return 0; + return false; /* * Check for special cases where we need to do something @@ -169,8 +125,8 @@ pathtrace_match(struct tcb *tcp) case SEN_sendfile64: case SEN_tee: /* fd, fd */ - return fdmatch(tcp, tcp->u_arg[0]) || - fdmatch(tcp, tcp->u_arg[1]); + return fdmatch_set(tcp, tcp->u_arg[0], set, nset) || + fdmatch_set(tcp, tcp->u_arg[1], set, nset); case SEN_faccessat: case SEN_fchmodat: @@ -188,28 +144,28 @@ pathtrace_match(struct tcb *tcp) case SEN_unlinkat: case SEN_utimensat: /* fd, path */ - return fdmatch(tcp, tcp->u_arg[0]) || - upathmatch(tcp, tcp->u_arg[1]); + return fdmatch_set(tcp, tcp->u_arg[0], set, nset) || + upathmatch_set(tcp, tcp->u_arg[1], set, nset); case SEN_link: case SEN_mount: case SEN_pivotroot: /* path, path */ - return upathmatch(tcp, tcp->u_arg[0]) || - upathmatch(tcp, tcp->u_arg[1]); + return upathmatch_set(tcp, tcp->u_arg[0], set, nset) || + upathmatch_set(tcp, tcp->u_arg[1], set, nset); case SEN_quotactl: /* x, path */ - return upathmatch(tcp, tcp->u_arg[1]); + return upathmatch_set(tcp, tcp->u_arg[1], set, nset); case SEN_linkat: case SEN_renameat2: case SEN_renameat: /* fd, path, fd, path */ - return fdmatch(tcp, tcp->u_arg[0]) || - fdmatch(tcp, tcp->u_arg[2]) || - upathmatch(tcp, tcp->u_arg[1]) || - upathmatch(tcp, tcp->u_arg[3]); + return fdmatch_set(tcp, tcp->u_arg[0], set, nset) || + fdmatch_set(tcp, tcp->u_arg[2], set, nset) || + upathmatch_set(tcp, tcp->u_arg[1], set, nset) || + upathmatch_set(tcp, tcp->u_arg[3], set, nset); case SEN_old_mmap: #if defined(S390) @@ -220,29 +176,28 @@ pathtrace_match(struct tcb *tcp) case SEN_mmap_pgoff: case SEN_ARCH_mmap: /* x, x, x, x, fd */ - return fdmatch(tcp, tcp->u_arg[4]); + return fdmatch_set(tcp, tcp->u_arg[4], set, nset); case SEN_symlinkat: /* path, fd, path */ - return fdmatch(tcp, tcp->u_arg[1]) || - upathmatch(tcp, tcp->u_arg[0]) || - upathmatch(tcp, tcp->u_arg[2]); + return fdmatch_set(tcp, tcp->u_arg[1], set, nset) || + upathmatch_set(tcp, tcp->u_arg[0], set, nset) || + upathmatch_set(tcp, tcp->u_arg[2], set, nset); case SEN_copy_file_range: case SEN_splice: /* fd, x, fd, x, x, x */ - return fdmatch(tcp, tcp->u_arg[0]) || - fdmatch(tcp, tcp->u_arg[2]); + return fdmatch_set(tcp, tcp->u_arg[0], set, nset) || + fdmatch_set(tcp, tcp->u_arg[2], set, nset); case SEN_epoll_ctl: /* x, x, fd, x */ - return fdmatch(tcp, tcp->u_arg[2]); - + return fdmatch_set(tcp, tcp->u_arg[2], set, nset); case SEN_fanotify_mark: /* x, x, x, fd, path */ - return fdmatch(tcp, tcp->u_arg[3]) || - upathmatch(tcp, tcp->u_arg[4]); + return fdmatch_set(tcp, tcp->u_arg[3], set, nset) || + upathmatch_set(tcp, tcp->u_arg[4], set, nset); case SEN_oldselect: case SEN_pselect6: @@ -281,7 +236,7 @@ pathtrace_match(struct tcb *tcp) nfds = (int) args[0]; /* Kernel rejects negative nfds, so we don't parse it either. */ if (nfds <= 0) - return 0; + return false; /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */ if (nfds > 1024*1024) nfds = 1024*1024; @@ -298,14 +253,14 @@ pathtrace_match(struct tcb *tcp) j = next_set_bit(fds, j, nfds); if (j < 0) break; - if (fdmatch(tcp, j)) { + if (fdmatch_set(tcp, j, set, nset)) { free(fds); - return 1; + return true; } } } free(fds); - return 0; + return false; } case SEN_poll: @@ -321,14 +276,14 @@ pathtrace_match(struct tcb *tcp) end = start + sizeof(fds) * nfds; if (nfds == 0 || end < start) - return 0; + return false; for (cur = start; cur < end; cur += sizeof(fds)) if ((umove(tcp, cur, &fds) == 0) - && fdmatch(tcp, fds.fd)) - return 1; + && fdmatch_set(tcp, fds.fd, set, nset)) + return true; - return 0; + return false; } case SEN_bpf: @@ -353,7 +308,7 @@ pathtrace_match(struct tcb *tcp) * 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 0; + return false; } /* @@ -362,10 +317,54 @@ pathtrace_match(struct tcb *tcp) */ if (s->sys_flags & TRACE_FILE) - return upathmatch(tcp, tcp->u_arg[0]); + return upathmatch_set(tcp, tcp->u_arg[0], set, nset); if (s->sys_flags & (TRACE_DESC | TRACE_NETWORK)) - return fdmatch(tcp, tcp->u_arg[0]); + return fdmatch_set(tcp, tcp->u_arg[0], set, nset); + + return false; +} + +/* + * Add a path to the set we're tracing. + * Specifying NULL will delete all paths. + */ +static void +storepath(const char *path) +{ + unsigned i; + + if (pathmatch_set(path, paths_selected, npaths_selected)) + return; /* already in table */ - return 0; + i = npaths_selected++; + paths_selected = xreallocarray(paths_selected, npaths_selected, + sizeof(paths_selected[0])); + paths_selected[i] = path; +} + +/* + * Add a path to the set we're tracing. Also add the canonicalized + * version of the path. Secifying NULL will delete all paths. + */ +void +pathtrace_select(const char *path) +{ + char *rpath; + + storepath(path); + + rpath = realpath(path, NULL); + + if (rpath == NULL) + return; + + /* if realpath and specified path are same, we're done */ + if (strcmp(path, rpath) == 0) { + free(rpath); + return; + } + + error_msg("Requested path '%s' resolved into '%s'", path, rpath); + storepath(rpath); } -- 2.11.0 ------------------------------------------------------------------------------ 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