[PATCH] pathtrace.c: introduce user-provided sets of paths

Nikolay Marchuk marchuk.nikolay.a at gmail.com
Sat Jul 8 08:28:56 UTC 2017


* defs.h (struct path_set): Add a definition for a path set.
(global_path_set): Add a declaration.
(tracing_paths): Change macro body to use global path set variable.
(pathtrace_select_set, pathtrace_match_set): Change declarations.
(pathtrace_select, pathtrace_match): New macroses.
* pathtrace.c (global_path_set): Define global path set.
(pathmatch, upathmatch, fdmatch, pathtrace_match_set): Accept user-provided
set of paths, change return type to bool.
(storepath, pathtrace_select_set): Accept user-provided set of paths.
---
 defs.h      |  15 ++++++--
 pathtrace.c | 120 ++++++++++++++++++++++++++++++------------------------------
 2 files changed, 71 insertions(+), 64 deletions(-)

diff --git a/defs.h b/defs.h
index b3a315f..e94e896 100644
--- a/defs.h
+++ b/defs.h
@@ -370,8 +370,11 @@ 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 struct path_set {
+	const char **paths_selected;
+	unsigned int num_selected;
+} global_path_set;
+#define tracing_paths (global_path_set.num_selected != 0)
 extern unsigned xflag;
 extern unsigned followfork;
 #ifdef USE_LIBUNWIND
@@ -497,8 +500,12 @@ extern long getrval2(struct tcb *);
 #endif
 
 extern const char *signame(const int);
-extern void pathtrace_select(const char *);
-extern int pathtrace_match(struct tcb *);
+extern void pathtrace_select_set(const char *, struct path_set *);
+extern bool pathtrace_match_set(struct tcb *, struct path_set *);
+#define pathtrace_select(tcp)	\
+	pathtrace_select_set(tcp, &global_path_set)
+#define pathtrace_match(tcp)	\
+	pathtrace_match_set(tcp, &global_path_set)
 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 9cb0ba7..d46ecd6 100644
--- a/pathtrace.c
+++ b/pathtrace.c
@@ -33,46 +33,46 @@
 
 #include "syscall.h"
 
-const char **paths_selected;
-static unsigned int num_selected;
+struct path_set global_path_set;
 
 /*
  * Return true if specified path matches one that we're tracing.
  */
-static int
-pathmatch(const char *path)
+static bool
+pathmatch(const char *path, struct path_set *set)
 {
 	unsigned i;
 
-	for (i = 0; i < num_selected; ++i) {
-		if (strcmp(path, paths_selected[i]) == 0)
-			return 1;
+	for (i = 0; i < set->num_selected; ++i) {
+		if (strcmp(path, set->paths_selected[i]) == 0)
+			return true;
 	}
-	return 0;
+	return false;
 }
 
 /*
  * Return true if specified path (in user-space) matches.
  */
-static int
-upathmatch(struct tcb *const tcp, const kernel_ulong_t upath)
+static bool
+upathmatch(struct tcb *const tcp, const kernel_ulong_t upath,
+	   struct path_set *set)
 {
 	char path[PATH_MAX + 1];
 
 	return umovestr(tcp, upath, sizeof(path), path) > 0 &&
-		pathmatch(path);
+		pathmatch(path, set);
 }
 
 /*
  * Return true if specified fd maps to a path we're tracing.
  */
-static int
-fdmatch(struct tcb *tcp, int fd)
+static bool
+fdmatch(struct tcb *tcp, int fd, struct path_set *set)
 {
 	char path[PATH_MAX + 1];
 	int n = getfdpath(tcp, fd, path, sizeof(path));
 
-	return n >= 0 && pathmatch(path);
+	return n >= 0 && pathmatch(path, set);
 }
 
 /*
@@ -80,17 +80,17 @@ fdmatch(struct tcb *tcp, int fd)
  * Specifying NULL will delete all paths.
  */
 static void
-storepath(const char *path)
+storepath(const char *path, struct path_set *set)
 {
 	unsigned i;
 
-	if (pathmatch(path))
+	if (pathmatch(path, set))
 		return; /* already in table */
 
-	i = num_selected++;
-	paths_selected = xreallocarray(paths_selected, num_selected,
-				       sizeof(paths_selected[0]));
-	paths_selected[i] = path;
+	i = set->num_selected++;
+	set->paths_selected = xreallocarray(set->paths_selected,
+			     set->num_selected, sizeof(set->paths_selected[0]));
+	set->paths_selected[i] = path;
 }
 
 /*
@@ -121,11 +121,11 @@ getfdpath(struct tcb *tcp, int fd, char *buf, unsigned bufsize)
  * version of the path.  Secifying NULL will delete all paths.
  */
 void
-pathtrace_select(const char *path)
+pathtrace_select_set(const char *path, struct path_set *set)
 {
 	char *rpath;
 
-	storepath(path);
+	storepath(path, set);
 
 	rpath = realpath(path, NULL);
 
@@ -139,22 +139,22 @@ pathtrace_select(const char *path)
 	}
 
 	error_msg("Requested path '%s' resolved into '%s'", path, rpath);
-	storepath(rpath);
+	storepath(rpath, set);
 }
 
 /*
  * Return true if syscall accesses a selected path
  * (or if no paths have been specified for tracing).
  */
-int
-pathtrace_match(struct tcb *tcp)
+bool
+pathtrace_match_set(struct tcb *tcp, struct path_set *set)
 {
 	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 +169,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(tcp, tcp->u_arg[0], set) ||
+			fdmatch(tcp, tcp->u_arg[1], set);
 
 	case SEN_faccessat:
 	case SEN_fchmodat:
@@ -188,28 +188,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(tcp, tcp->u_arg[0], set) ||
+			upathmatch(tcp, tcp->u_arg[1], set);
 
 	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(tcp, tcp->u_arg[0], set) ||
+			upathmatch(tcp, tcp->u_arg[1], set);
 
 	case SEN_quotactl:
 		/* x, path */
-		return upathmatch(tcp, tcp->u_arg[1]);
+		return upathmatch(tcp, tcp->u_arg[1], set);
 
 	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(tcp, tcp->u_arg[0], set) ||
+			fdmatch(tcp, tcp->u_arg[2], set) ||
+			upathmatch(tcp, tcp->u_arg[1], set) ||
+			upathmatch(tcp, tcp->u_arg[3], set);
 
 	case SEN_old_mmap:
 #if defined(S390)
@@ -220,29 +220,29 @@ 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(tcp, tcp->u_arg[4], set);
 
 	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(tcp, tcp->u_arg[1], set) ||
+			upathmatch(tcp, tcp->u_arg[0], set) ||
+			upathmatch(tcp, tcp->u_arg[2], set);
 
 	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(tcp, tcp->u_arg[0], set) ||
+			fdmatch(tcp, tcp->u_arg[2], set);
 
 	case SEN_epoll_ctl:
 		/* x, x, fd, x */
-		return fdmatch(tcp, tcp->u_arg[2]);
+		return fdmatch(tcp, tcp->u_arg[2], set);
 
 
 	case SEN_fanotify_mark:
 		/* x, x, x, fd, path */
-		return fdmatch(tcp, tcp->u_arg[3]) ||
-			upathmatch(tcp, tcp->u_arg[4]);
+		return fdmatch(tcp, tcp->u_arg[3], set) ||
+			upathmatch(tcp, tcp->u_arg[4], set);
 
 	case SEN_oldselect:
 	case SEN_pselect6:
@@ -259,13 +259,13 @@ pathtrace_match(struct tcb *tcp)
 		if (SEN_oldselect == s->sen) {
 			if (sizeof(*select_args) == sizeof(*oldselect_args)) {
 				if (umove(tcp, tcp->u_arg[0], &select_args)) {
-					return 0;
+					return false;
 				}
 			} else {
 				unsigned int n;
 
 				if (umove(tcp, tcp->u_arg[0], &oldselect_args)) {
-					return 0;
+					return false;
 				}
 
 				for (n = 0; n < 5; ++n) {
@@ -281,7 +281,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 +298,14 @@ pathtrace_match(struct tcb *tcp)
 				j = next_set_bit(fds, j, nfds);
 				if (j < 0)
 					break;
-				if (fdmatch(tcp, j)) {
+				if (fdmatch(tcp, j, set)) {
 					free(fds);
-					return 1;
+					return true;
 				}
 			}
 		}
 		free(fds);
-		return 0;
+		return false;
 	}
 
 	case SEN_poll:
@@ -321,14 +321,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(tcp, fds.fd, set))
+				return true;
 
-		return 0;
+		return false;
 	}
 
 	case SEN_bpf:
@@ -353,7 +353,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 +362,10 @@ pathtrace_match(struct tcb *tcp)
 	 */
 
 	if (s->sys_flags & TRACE_FILE)
-		return upathmatch(tcp, tcp->u_arg[0]);
+		return upathmatch(tcp, tcp->u_arg[0], set);
 
 	if (s->sys_flags & (TRACE_DESC | TRACE_NETWORK))
-		return fdmatch(tcp, tcp->u_arg[0]);
+		return fdmatch(tcp, tcp->u_arg[0], set);
 
-	return 0;
+	return false;
 }
-- 
2.1.4





More information about the Strace-devel mailing list