[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