[PATCH v1 1/1] pathtrace.c: introduce pathtrace_match_set instead of pathtrace_match

Victor Krapivensky krapivenskiy.va at phystech.edu
Fri Jul 7 20:45:49 UTC 2017


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





More information about the Strace-devel mailing list