On 08.07.2017 03:45, Victor Krapivensky wrote: > 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. I don't think that it is necessary to rename static functions. These functions don't change their behaviour a lot and are used only in pathtrace.c. Only pathtrace_match renaming is useful for compatibility. > --- > 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) I have also implemented similar pathtrace api for path filter, but my implementation uses new path_set struct to pass both paths_selected and num_selected, and pathtrace_select also supports user-provided sets. I will send my version of implementation in next message. > 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); > } >
signature.asc
Description: OpenPGP digital signature
------------------------------------------------------------------------------ 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