summaryrefslogtreecommitdiff
path: root/src/pathtrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pathtrace.c')
-rw-r--r--src/pathtrace.c58
1 files changed, 35 insertions, 23 deletions
diff --git a/src/pathtrace.c b/src/pathtrace.c
index f94f2e60d..3a97f4557 100644
--- a/src/pathtrace.c
+++ b/src/pathtrace.c
@@ -27,6 +27,9 @@ struct path_set global_path_set;
static bool
pathmatch(const char *path, struct path_set *set)
{
+ if (!set)
+ return false;
+
for (unsigned int i = 0; i < set->num_selected; ++i) {
if (strcmp(path, set->paths_selected[i].path) == 0)
return true;
@@ -41,6 +44,9 @@ static bool
upathmatch(struct tcb *const tcp, const kernel_ulong_t upath,
struct path_set *set)
{
+ if (!set)
+ return false;
+
char path[PATH_MAX + 1];
return umovestr(tcp, upath, sizeof(path), path) > 0 &&
@@ -51,8 +57,13 @@ upathmatch(struct tcb *const tcp, const kernel_ulong_t upath,
* Return true if specified fd maps to a path we're tracing.
*/
static bool
-fdmatch(struct tcb *tcp, int fd, struct path_set *set)
+fdmatch(struct tcb *tcp, int fd, struct path_set *set, struct number_set *fdset)
{
+ if (fdset && fd >= 0 && is_number_in_set(fd, fdset))
+ return true;
+ if (!set)
+ return false;
+
char path[PATH_MAX + 1];
int n = getfdpath(tcp, fd, path, sizeof(path));
@@ -194,7 +205,7 @@ pathtrace_select_set(const char *path, struct path_set *set)
static bool
match_xselect_args(struct tcb *tcp, const kernel_ulong_t *args,
- struct path_set *set)
+ struct path_set *set, struct number_set *fdset)
{
/* Kernel truncates arg[0] to int, we do the same. */
int nfds = (int) args[0];
@@ -216,7 +227,7 @@ match_xselect_args(struct tcb *tcp, const kernel_ulong_t *args,
j = next_set_bit(fds, j, nfds);
if (j < 0)
break;
- if (fdmatch(tcp, j, set)) {
+ if (fdmatch(tcp, j, set, fdset)) {
free(fds);
return true;
}
@@ -232,7 +243,8 @@ match_xselect_args(struct tcb *tcp, const kernel_ulong_t *args,
* (or if no paths have been specified for tracing).
*/
bool
-pathtrace_match_set(struct tcb *tcp, struct path_set *set)
+pathtrace_match_set(struct tcb *tcp, struct path_set *set,
+ struct number_set *fdset)
{
const struct_sysent *s;
@@ -254,8 +266,8 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
case SEN_sendfile64:
case SEN_tee:
/* fd, fd */
- return fdmatch(tcp, tcp->u_arg[0], set) ||
- fdmatch(tcp, tcp->u_arg[1], set);
+ return fdmatch(tcp, tcp->u_arg[0], set, fdset) ||
+ fdmatch(tcp, tcp->u_arg[1], set, fdset);
case SEN_execveat:
case SEN_faccessat:
@@ -280,7 +292,7 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
case SEN_utimensat_time32:
case SEN_utimensat_time64:
/* fd, path */
- return fdmatch(tcp, tcp->u_arg[0], set) ||
+ return fdmatch(tcp, tcp->u_arg[0], set, fdset) ||
upathmatch(tcp, tcp->u_arg[1], set);
case SEN_link:
@@ -300,8 +312,8 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
case SEN_renameat2:
case SEN_renameat:
/* fd, path, fd, path */
- return fdmatch(tcp, tcp->u_arg[0], set) ||
- fdmatch(tcp, tcp->u_arg[2], set) ||
+ return fdmatch(tcp, tcp->u_arg[0], set, fdset) ||
+ fdmatch(tcp, tcp->u_arg[2], set, fdset) ||
upathmatch(tcp, tcp->u_arg[1], set) ||
upathmatch(tcp, tcp->u_arg[3], set);
@@ -314,7 +326,7 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
kernel_ulong_t *args =
fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 6);
- return args && fdmatch(tcp, args[4], set);
+ return args && fdmatch(tcp, args[4], set, fdset);
}
#endif /* HAVE_ARCH_OLD_MMAP */
@@ -323,22 +335,22 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
case SEN_mmap_pgoff:
case SEN_ARCH_mmap:
/* x, x, x, x, fd */
- return fdmatch(tcp, tcp->u_arg[4], set);
+ return fdmatch(tcp, tcp->u_arg[4], set, fdset);
case SEN_symlinkat:
/* x, fd, path */
- return fdmatch(tcp, tcp->u_arg[1], set) ||
+ return fdmatch(tcp, tcp->u_arg[1], set, fdset) ||
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], set) ||
- fdmatch(tcp, tcp->u_arg[2], set);
+ return fdmatch(tcp, tcp->u_arg[0], set, fdset) ||
+ fdmatch(tcp, tcp->u_arg[2], set, fdset);
case SEN_epoll_ctl:
/* x, x, fd, x */
- return fdmatch(tcp, tcp->u_arg[2], set);
+ return fdmatch(tcp, tcp->u_arg[2], set, fdset);
case SEN_fanotify_mark:
@@ -346,7 +358,7 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
/* x, x, mask (64 bit), fd, path */
unsigned long long mask = 0;
unsigned int argn = getllval(tcp, &mask, 2);
- return fdmatch(tcp, tcp->u_arg[argn], set) ||
+ return fdmatch(tcp, tcp->u_arg[argn], set, fdset) ||
upathmatch(tcp, tcp->u_arg[argn + 1], set);
}
#if HAVE_ARCH_OLD_SELECT
@@ -355,13 +367,13 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
kernel_ulong_t *args =
fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 5);
- return args && match_xselect_args(tcp, args, set);
+ return args && match_xselect_args(tcp, args, set, fdset);
}
#endif
case SEN_pselect6_time32:
case SEN_pselect6_time64:
case SEN_select:
- return match_xselect_args(tcp, tcp->u_arg, set);
+ return match_xselect_args(tcp, tcp->u_arg, set, fdset);
case SEN_poll_time32:
case SEN_poll_time64:
case SEN_ppoll_time32:
@@ -381,7 +393,7 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
for (kernel_ulong_t cur = start; cur < end; cur += sizeof(fds)) {
if (umove(tcp, cur, &fds))
break;
- if (fdmatch(tcp, fds.fd, set))
+ if (fdmatch(tcp, fds.fd, set, fdset))
return true;
}
@@ -394,10 +406,10 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
switch (cmd) {
case 3 /* FSCONFIG_SET_PATH */:
case 4 /* FSCONFIG_SET_PATH_EMPTY */:
- return fdmatch(tcp, tcp->u_arg[4], set) ||
- upathmatch(tcp, tcp->u_arg[3], set);
+ return fdmatch(tcp, tcp->u_arg[4], set, fdset)
+ || upathmatch(tcp, tcp->u_arg[3], set);
case 5 /* FSCONFIG_SET_FD */:
- return fdmatch(tcp, tcp->u_arg[4], set);
+ return fdmatch(tcp, tcp->u_arg[4], set, fdset);
}
return false;
@@ -461,7 +473,7 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
return upathmatch(tcp, tcp->u_arg[0], set);
if (s->sys_flags & (TRACE_DESC | TRACE_NETWORK))
- return fdmatch(tcp, tcp->u_arg[0], set);
+ return fdmatch(tcp, tcp->u_arg[0], set, fdset);
return false;
}