diff --git a/examples/opensnoop_example.txt b/examples/opensnoop_example.txt index afa54fa..133578c 100644 --- a/examples/opensnoop_example.txt +++ b/examples/opensnoop_example.txt @@ -28,10 +28,11 @@ The first several lines show opensnoop catching itself initializing. Use -h to print the USAGE message: # ./opensnoop -h -USAGE: opensnoop [-htx] [-d secs] [-p PID] [-n name] [filename] +USAGE: opensnoop [-htx] [-d secs] [-p PID] [-T TID] [-n name] [filename] -d seconds # trace duration, and use buffers - -n name # process name to match on I/O issue - -p PID # PID to match on I/O issue + -n name # process name to match on open + -p PID # PID to match on open + -L TID # thread id to match on open -t # include time (seconds) -x # only show failed opens -h # this usage message diff --git a/man/man8/opensnoop.8 b/man/man8/opensnoop.8 index 7a3635f..a09eda3 100644 --- a/man/man8/opensnoop.8 +++ b/man/man8/opensnoop.8 @@ -3,7 +3,7 @@ opensnoop \- trace open() syscalls with file details. Uses Linux ftrace. .SH SYNOPSIS .B opensnoop -[\-htx] [\-d secs] [\-p pid] [\-n name] [filename] +[\-htx] [\-d secs] [\-p pid] [\-L tid] [\-n name] [filename] .SH DESCRIPTION This traces open() syscalls, showing the file name (pathname) and returned file descriptor number (or \-1, for error). @@ -41,6 +41,9 @@ expressions are allowed. This is post-filtered using awk. \-p PID Only trace this process ID. This is filtered in-kernel. .TP +\-L TID +Only trace this thread ID. This is filtered in-kernel. +.TP \-t Include timestamps, in seconds. .TP diff --git a/opensnoop b/opensnoop index 7e0bb48..6d382fb 100755 --- a/opensnoop +++ b/opensnoop @@ -13,7 +13,7 @@ # It is a workaround, and proof of concept for ftrace, until more kernel tracing # functionality is available. # -# USAGE: ./opensnoop [-htx] [-d secs] [-p pid] [-n name] [filename] +# USAGE: ./opensnoop [-htx] [-d secs] [-p pid] [-L tid] [-n name] [filename] # # Run "opensnoop -h" for full usage. # @@ -48,16 +48,17 @@ ### default variables tracing=/sys/kernel/debug/tracing flock=/var/tmp/.ftrace-lock; wroteflock=0 -opt_duration=0; duration=; opt_name=0; name=; opt_pid=0; pid=; ftext= -opt_time=0; opt_fail=0; opt_file=0; file= +opt_duration=0; duration=; opt_name=0; name=; opt_pid=0; pid=; opt_tid=0; tid= +ftext=; opt_time=0; opt_fail=0; opt_file=0; file= trap ':' INT QUIT TERM PIPE HUP # sends execution to end tracing section function usage { cat <<-END >&2 - USAGE: opensnoop [-htx] [-d secs] [-p PID] [-n name] [filename] + USAGE: opensnoop [-htx] [-d secs] [-p PID] [-L TID] [-n name] [filename] -d seconds # trace duration, and use buffers - -n name # process name to match on I/O issue - -p PID # PID to match on I/O issue + -n name # process name to match on open + -p PID # PID to match on open + -L TID # PID to match on open -t # include time (seconds) -x # only show failed opens -h # this usage message @@ -87,7 +88,7 @@ function end { cd $tracing warn "echo 0 > events/kprobes/getnameprobe/enable" warn "echo 0 > events/syscalls/sys_exit_open/enable" - if (( opt_pid )); then + if (( opt_pid || opt_tid )); then warn "echo 0 > events/kprobes/getnameprobe/filter" warn "echo 0 > events/syscalls/sys_exit_open/filter" fi @@ -110,12 +111,13 @@ function edie { } ### process options -while getopts d:hn:p:tx opt +while getopts d:hn:p:L:tx opt do case $opt in d) opt_duration=1; duration=$OPTARG ;; n) opt_name=1; name=$OPTARG ;; p) opt_pid=1; pid=$OPTARG ;; + L) opt_tid=1; tid=$OPTARG ;; t) opt_time=1 ;; x) opt_fail=1 ;; h|?) usage ;; @@ -130,8 +132,10 @@ fi (( $# )) && usage ### option logic -(( opt_pid && opt_name )) && die "ERROR: use either -p or -n." +(( opt_pid + opt_name + opt_tid > 1 )) && \ + die "ERROR: use at most one of -p, -n, -L." (( opt_pid )) && ftext=" issued by PID $pid" +(( opt_tid )) && ftext=" issued by TID $tid" (( opt_name )) && ftext=" issued by process name \"$name\"" (( opt_file )) && ftext="$ftext for filenames containing \"$file\"" if (( opt_duration )); then @@ -167,12 +171,24 @@ if ! echo $kprobe >> kprobe_events; then edie "ERROR: adding a kprobe for getname(). Exiting." fi if (( opt_pid )); then - if ! echo "common_pid==$pid" > events/kprobes/getnameprobe/filter || \ - ! echo "common_pid==$pid" > events/syscalls/sys_exit_open/filter + filter= + for tid in /proc/$pid/task/*; do + filter="$filter || common_pid == ${tid##*/}" + done + filter=${filter:3} # trim leading ' || ' (four characters) + if ! echo $filter > events/kprobes/getnameprobe/filter || \ + ! echo $filter > events/syscalls/sys_exit_open/filter then edie "ERROR: setting -p $pid. Exiting." fi fi +if (( opt_tid )); then + if ! echo "common_pid == $tid" > events/kprobes/getnameprobe/filter || \ + ! echo "common_pid == $tid" > events/syscalls/sys_exit_open/filter + then + edie "ERROR: setting -L $tid. Exiting." + fi +fi if ! echo 1 > events/kprobes/getnameprobe/enable; then edie "ERROR: enabling kprobe for getname(). Exiting." fi