From 09c781b184ac6e2104715a6a22ec4c766656ac75 Mon Sep 17 00:00:00 2001 From: Nikolay Marchuk Date: Sat, 8 Jul 2017 15:28:56 +0700 Subject: [PATCH] pathtrace.c: introduce user-provided sets of paths * defs.h (struct path_set): New structure. (global_path_set): New variable prototype. (tracing_paths): Change macro body to use global_path_set variable. (pathtrace_select_set): Add "struct path_set *" argument. (pathtrace_match_set): Likewise. Change return type to bool. (pathtrace_select, pathtrace_match): Change into thin macro wrappers around pathtrace_select_set and pathtrace_match_set, repsectively. * pathtrace.c (global_path_set): New variable. (storepath, pathtrace_select_set): Add "struct path_set *" argument. (pathmatch, upathmatch, fdmatch, pathtrace_match_set): Likewise. Change return type to bool. --- defs.h | 15 +++++-- pathtrace.c | 121 ++++++++++++++++++++++++++-------------------------- 2 files changed, 72 insertions(+), 64 deletions(-) diff --git a/defs.h b/defs.h index c6de8c1e..21f1704e 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 9cb0ba77..9f3674a4 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,18 @@ 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 +122,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 +140,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 +170,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 +189,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 +221,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 +260,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 +282,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 +299,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 +322,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 +354,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 +363,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.40.0