[PATCH v1 1/1] pathtrace.c: introduce pathtrace_match_set instead of pathtrace_match
Nikolay Marchuk
marchuk.nikolay.a at gmail.com
Sat Jul 8 08:25:43 UTC 2017
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);
> }
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 213 bytes
Desc: OpenPGP digital signature
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20170708/4039d87d/attachment.bin>
More information about the Strace-devel
mailing list