RFC: path display and path filtering features.

Grant Edwards grant.b.edwards at gmail.com
Fri Feb 18 16:20:24 UTC 2011


On 2011-02-18, Dmitry V. Levin <ldv at altlinux.org> wrote:
> On Thu, Feb 17, 2011 at 11:29:27AM -0600, Grant Edwards wrote:
>> I've re-written the path display/trace features.  Attached is a
>> snapshot of the diffs against the current git HEAD.  Changes since the
>> first version I posted follow:
>
> Thanks a lot.  Now we have a working PoC to discuss details.
>
>>  * Removed the code that tracked fd-table state based on syscalls.  It
>>    now does a readlink() on /proc/<pid>/fd/<fd> to find the path
>>    associated with a file descriptor.
>
> Linux kernel treats file descriptors as unsigned integers, but
> sysctl_nr_open is still limited to 0x100000, so I'd add an extra check
> for fd < 0 in getpath().

Done.

>>  * Change the -P option so that instead of accepting a colon-separated
>>    list of paths, it accepts a single path.  Multiple -P options can
>>    be specified to trace multiple paths.
>
> Maybe an attempt to exceed MAXSELECTED in pathtrace_select() should be
> treated as a fatal error.

Done.

>>  * Change the way that file descriptors are printed by the display
>>    functions.  Instead of using "%s" and a function that returns a
>>    formatted string, they now use a printfd() function analogous to
>>    the printpath() function.
>
> BTW, there is a long standing bug in decoding of file descriptors on
> 64bit architectures, and it's time to fix it in one place.
>
> For example,
> $ cat close.c
> int close(unsigned long fd);
> int main(void){return !!close(0xffffffff00000000UL);}
> $ gcc -Wall -O2 close.c -o close
> $ strace -eclose -o'|tail -1' ./close
> close(-4294967296)                      = 0
> $ strace -y -eclose -o'|tail -1' ./close
> close(-4294967296</dev/pts/1>)          = 0
>
> The fix is to change "fd" type in printfd() from long to int, and to print
> it using %d format.

Done.

>>  * Added handling (for Linux) for system calls where we need to look
>>    at something other than arg[0] for a descriptor/path.
>
> There is a lot of work to do.
> Some non-arg[0] syscalls are not listed in pathtrace_match(); for
> example, sys_dup3 and sys_old_mmap are listed but sys_dup2 and
> sys_mmap are not.

The missing dup2 appears to have been an oversight on my part.

sys_mmap is missing becuase I only examined system calls that had the
TRACE_DESC flag set in the sysent table.

I've added both of them and added the TRACE_DESC flag to the sysent
entry for sys_mmap.

> Some struct sysent records still have outdated sys_flags; for example,
> TRACE_DESC is not set for sys_mmap and sys_fadvise64*.

Fixed.

[I notice that the flags value was TF on m68k and s390x, but it was 0
for the rest.  I've changed it to TD for all architectures.]


> I'm not sure that we can ignore all cases where syscalls return file
> descriptor as their return value.

That wasn't my intent, and I don't think that's what the code does.

I meant to ignore system calls who returned file descriptors (and
therefore had the TRACE_DESC flag set), but didn't have arguments that
were file paths or open file descriptors.

I assume you're talking about are this bit of code:

  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 ||
      s->sys_func == sys_timerfd_gettime ||
      s->sys_func == sys_timerfd_settime)
    {
      // these either return fd's or they do other things we don't
      // yet handle
      return 0;
    }

How's this?


  if (s->sys_func == printargs ||
      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 ||
      s->sys_func == sys_timerfd_settime ||
      s->sys_func == sys_timerfd_gettime)
    {
      // these have TRACE_FILE or TRACE_DESCRIPTOR set, but they don't
      // have any file descriptor or path args to test
      return 0;
    }

  if (s->sys_func == sys_poll ||
      s->sys_func == sys_ppoll  ||
      s->sys_func == sys_select ||
      s->sys_func == sys_oldselect  ||
      s->sys_func == sys_pselect6)
    {
      // these have arguments that refer indirectly to file
      // descriptors, and we need to add code to handle them.
      return 0;
    }
    
I'm going to work on checking the fd's referred in the args to the
poll/select calls. Are there other calls in that list that have
path/fd arguments that should be tested?  


> For example,
> $ strace -s4 -y -P /lib64/libc-2.11.3.so -P /lib64/libc.so.6 /bin/echo
> open("/lib64/libc.so.6", O_RDONLY)      = 3
> read(3</lib64/libc-2.11.3.so>, "\177ELF"..., 832) = 832
> fstat(3</lib64/libc-2.11.3.so>, {st_mode=S_IFREG|0755, st_size=1465744, ...}) = 0
> close(3</lib64/libc-2.11.3.so>)         = 0
>
> The pathname passed to open(2) is a symlink, and /proc/<pid>/fd/<fd>
> points to the canonicalized pathname, so -P /lib64/libc-2.11.3.so
> won't catch this open(2) call now.

I can think of a couple options:

 1) Store both the canoical and "as-provided" versions of paths
    passed to -P.

 2) Canonicalize the pathname passed to -P, and also canonicalize
    path arguments when checking for a match. 

Either would be OK with me.
    
-- 
Grant Edwards               grant.b.edwards        Yow! Are we wet yet?
                                  at               
                              gmail.com            





More information about the Strace-devel mailing list