[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