RFC: path display and path filtering features.

Grant Edwards grant.b.edwards at gmail.com
Wed Feb 16 18:10:55 UTC 2011


On 2011-02-16, Dmitry V. Levin <ldv at altlinux.org> wrote:

> Even with these complications, readlink-based approach seems to be
> more reliable and easy to implement and support.

I agree.  I've tossed out the fd-tracking code.

Once again, premature optimization proves to be a mistake.

> Another issue is how to match paths reliably without introducing code
> into every parser function. The approach implemented in your
> pathtrace_match() is not capable to handle syscalls that take several
> pathname arguments like rename(2), or pathname argument along with
> descriptor argument like openat(2).

Right.  I've extended pathtrace_match so it explicity handles cases
other than a single fd/path in arg[0].

> Possible solution could be extending struct sysent with more generic
> information about syscalls, e.g. with two 8-bit bitsets describing
> pathname-like and descriptor-like arguments.

That's the approach used by the python version of strace: the "sysent"
table contains type and name information about each argument.

It would be cleaner than my approach and keep info on systemcalls more
localized.

Below is the pathtrace_match() function I'm currently using.  I don't
like it much because adds another place that contains sycall-specific
information.

Would people be agreeable to adding argument type info (or argument
format function pointers) to the sysent table?  In addition to making
the fd/path match function simpler, it might allow the "printargs"
function to handle many more cases.


----------------------------------------------------------------------
// return true if syscall accesses a selected path (or if no paths
// have been specified for tracing).
int pathtrace_match(struct tcb *tcp)
{
  char path[1024];
  const struct sysent *s;

  if (selected[0] == NULL)
    return 1;

  s = &sysent[tcp->scno];

  if (!(s->sys_flags & (TRACE_FILE | TRACE_DESC)))
    return 0;

  // check for special cases where we need to do something other than
  // test arg[0]

#ifdef LINUX
  if (s->sys_func == sys_dup3 ||
      s->sys_func == sys_sendfile ||
      s->sys_func == sys_sendfile64 ||
      !strcmp(s->sys_name,"tee"))
    {
      // fd,fd
      return fdmatch(tcp->pid,tcp->u_arg[0]) || fdmatch(tcp->pid,tcp->u_arg[1]);
    }

  if (s->sys_func == sys_inotify_add_watch ||
      s->sys_func == sys_faccessat ||
      s->sys_func == sys_fchmodat ||
      s->sys_func == sys_futimesat ||
      s->sys_func == sys_mkdirat ||
      s->sys_func == sys_unlinkat ||
      s->sys_func == sys_newfstatat ||
      s->sys_func == sys_mknodat ||
      s->sys_func == sys_openat ||
      s->sys_func == sys_readlinkat ||
      s->sys_func == sys_utimensat ||
      s->sys_func == sys_fchownat ||
      s->sys_func == sys_pipe2)
    {
      // fd,path

      return fdmatch(tcp->pid,tcp->u_arg[0]) ||
             (umovestr(tcp,tcp->u_arg[1],sizeof path,path), pathmatch(tcp->pid,path));
    }

  if (s->sys_func == sys_link ||
      s->sys_func == sys_pivotroot ||
      s->sys_func == sys_rename ||
      s->sys_func == sys_symlink ||
      s->sys_func == sys_mount)
    {
      // path,path
      return (umovestr(tcp,tcp->u_arg[0],sizeof path,path), pathmatch(tcp->pid,path)) ||
             (umovestr(tcp,tcp->u_arg[1],sizeof path,path), pathmatch(tcp->pid,path));
    }

  if (s->sys_func == sys_renameat ||
      s->sys_func == sys_linkat)
    {
      // fd,path,fd,path
      return fdmatch(tcp->pid,tcp->u_arg[0]) ||
             fdmatch(tcp->pid,tcp->u_arg[2]) ||
             (umovestr(tcp,tcp->u_arg[1],sizeof path,path), pathmatch(tcp->pid,path)) ||
             (umovestr(tcp,tcp->u_arg[3],sizeof path,path), pathmatch(tcp->pid,path));
    }

  if (s->sys_func == sys_old_mmap)
    {
      // x,x,x,x,fd
      return fdmatch(tcp->pid,tcp->u_arg[4]);
    }

  if (s->sys_func == sys_symlinkat)
    {
      // path,fd,path
      return fdmatch(tcp->pid,tcp->u_arg[1]) ||
             (umovestr(tcp,tcp->u_arg[0],sizeof path,path), pathmatch(tcp->pid,path)) ||
             (umovestr(tcp,tcp->u_arg[2],sizeof path,path), pathmatch(tcp->pid,path));
    }


  if (s->sys_func == sys_poll ||
      s->sys_func == printargs ||
      s->sys_func == sys_ppoll  ||
      s->sys_func == sys_select ||
      s->sys_func == sys_oldselect  ||
      s->sys_func == sys_pselect6  ||
      s->sys_func == sys_pipe  ||
      s->sys_func == sys_pipe2  ||
      s->sys_func == sys_eventfd2  ||
      s->sys_func == sys_eventfd  ||
      s->sys_func == sys_inotify_init1  ||
      s->sys_func == sys_timerfd_create)
    {
      // these either return fd's or they do other things we don't
      // know how to handle
      return 0;
    }
#else
#  warning "path tracing only using arg[0]"
#endif


  if (s->sys_flags & TRACE_FILE)
    {
      umovestr(tcp,tcp->u_arg[0],sizeof path,path);
      return pathmatch(tcp->pid,path);
    }

  if (s->sys_flags & TRACE_DESC)
    {
      return fdmatch(tcp->pid,tcp->u_arg[0]);
    }

  return 0;
}



-- 
Grant Edwards               grant.b.edwards        Yow! I feel like a wet
                                  at               parking meter on Darvon!
                              gmail.com            





More information about the Strace-devel mailing list