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);
>  }
> 

Attachment: 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

Reply via email to