Merge pull request #2113 from takumakume/opensnoop-display-uid

opensnoop: supported UID options
diff --git a/man/man8/opensnoop.8 b/man/man8/opensnoop.8
index 6989b52..9d99a90 100644
--- a/man/man8/opensnoop.8
+++ b/man/man8/opensnoop.8
@@ -27,6 +27,9 @@
 \-T
 Include a timestamp column.
 .TP
+\-U
+Show UID.
+.TP
 \-x
 Only print failed opens.
 .TP
@@ -36,6 +39,9 @@
 \-t TID
 Trace this thread ID only (filtered in-kernel).
 .TP
+\-u UID
+Trace this UID only (filtered in-kernel).
+.TP
 \-d DURATION
 Total duration of trace in seconds.
 .TP
@@ -61,6 +67,10 @@
 #
 .B opensnoop \-T
 .TP
+Show UID:
+#
+.B opensnoop \-U
+.TP
 Trace only open() syscalls that failed:
 #
 .B opensnoop \-x
@@ -69,6 +79,10 @@
 #
 .B opensnoop \-p 181
 .TP
+Trace UID 1000 only:
+#
+.B opensnoop \-u 1000
+.TP
 Trace all open() syscalls from processes where its name partially matches 'ed':
 #
 .B opensnoop \-n ed
@@ -85,6 +99,9 @@
 TIME(s)
 Time of the call, in seconds.
 .TP
+UID
+User ID
+.TP
 PID
 Process ID
 .TP
diff --git a/tools/opensnoop.py b/tools/opensnoop.py
index d8d06d1..3d6cc15 100755
--- a/tools/opensnoop.py
+++ b/tools/opensnoop.py
@@ -13,6 +13,7 @@
 # 29-Apr-2016   Allan McAleavy  Updated for BPF_PERF_OUTPUT.
 # 08-Oct-2016   Dina Goldshtein Support filtering by PID and TID.
 # 28-Dec-2018   Tim Douglas     Print flags argument, enable filtering
+# 06-Jan-2019   Takuma Kume     Support filtering by UID
 
 from __future__ import print_function
 from bcc import ArgString, BPF
@@ -26,9 +27,11 @@
 examples = """examples:
     ./opensnoop           # trace all open() syscalls
     ./opensnoop -T        # include timestamps
+    ./opensnoop -U        # include UID
     ./opensnoop -x        # only show failed opens
     ./opensnoop -p 181    # only trace PID 181
     ./opensnoop -t 123    # only trace TID 123
+    ./opensnoop -u 1000   # only trace UID 1000
     ./opensnoop -d 10     # trace for 10 seconds only
     ./opensnoop -n main   # only print process names containing "main"
     ./opensnoop -e        # show extended fields
@@ -40,12 +43,16 @@
     epilog=examples)
 parser.add_argument("-T", "--timestamp", action="store_true",
     help="include timestamp on output")
+parser.add_argument("-U", "--print-uid", action="store_true",
+    help="print UID column")
 parser.add_argument("-x", "--failed", action="store_true",
     help="only show failed opens")
 parser.add_argument("-p", "--pid",
     help="trace this PID only")
 parser.add_argument("-t", "--tid",
     help="trace this TID only")
+parser.add_argument("-u", "--uid",
+    help="trace this UID only")
 parser.add_argument("-d", "--duration",
     help="total duration of trace in seconds")
 parser.add_argument("-n", "--name",
@@ -86,6 +93,7 @@
 struct data_t {
     u64 id;
     u64 ts;
+    u32 uid;
     int ret;
     char comm[TASK_COMM_LEN];
     char fname[NAME_MAX];
@@ -101,8 +109,10 @@
     u64 id = bpf_get_current_pid_tgid();
     u32 pid = id >> 32; // PID is higher part
     u32 tid = id;       // Cast and get the lower part
+    u32 uid = bpf_get_current_uid_gid();
 
     PID_TID_FILTER
+    UID_FILTER
     FLAGS_FILTER
     if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) {
         val.id = id;
@@ -131,6 +141,7 @@
     bpf_probe_read(&data.fname, sizeof(data.fname), (void *)valp->fname);
     data.id = valp->id;
     data.ts = tsp / 1000;
+    data.uid = bpf_get_current_uid_gid();
     data.flags = valp->flags; // EXTENDED_STRUCT_MEMBER
     data.ret = PT_REGS_RC(ctx);
 
@@ -148,6 +159,11 @@
         'if (pid != %s) { return 0; }' % args.pid)
 else:
     bpf_text = bpf_text.replace('PID_TID_FILTER', '')
+if args.uid:
+    bpf_text = bpf_text.replace('UID_FILTER',
+        'if (uid != %s) { return 0; }' % args.uid)
+else:
+    bpf_text = bpf_text.replace('UID_FILTER', '')
 if args.flag_filter:
     bpf_text = bpf_text.replace('FLAGS_FILTER',
         'if (!(flags & %d)) { return 0; }' % flag_filter_mask)
@@ -173,6 +189,7 @@
     _fields_ = [
         ("id", ct.c_ulonglong),
         ("ts", ct.c_ulonglong),
+        ("uid", ct.c_uint32),
         ("ret", ct.c_int),
         ("comm", ct.c_char * TASK_COMM_LEN),
         ("fname", ct.c_char * NAME_MAX),
@@ -184,6 +201,8 @@
 # header
 if args.timestamp:
     print("%-14s" % ("TIME(s)"), end="")
+if args.print_uid:
+    print("%-6s" % ("UID"), end="")
 print("%-6s %-16s %4s %3s " %
       ("TID" if args.tid else "PID", "COMM", "FD", "ERR"), end="")
 if args.extended_fields:
@@ -216,6 +235,9 @@
         delta = event.ts - initial_ts
         print("%-14.9f" % (float(delta) / 1000000), end="")
 
+    if args.print_uid:
+        print("%-6d" % event.uid, end="")
+
     print("%-6d %-16s %4d %3d " %
           (event.id & 0xffffffff if args.tid else event.id >> 32,
            event.comm.decode('utf-8', 'replace'), fd_s, err), end="")
diff --git a/tools/opensnoop_example.txt b/tools/opensnoop_example.txt
index dc515e5..c504ba4 100644
--- a/tools/opensnoop_example.txt
+++ b/tools/opensnoop_example.txt
@@ -65,6 +65,27 @@
 second.
 
 
+The -U option include UID on output:
+
+# ./opensnoop -U
+UID   PID    COMM               FD ERR PATH
+0     27063  vminfo              5   0 /var/run/utmp
+103   628    dbus-daemon        -1   2 /usr/local/share/dbus-1/system-services
+103   628    dbus-daemon        18   0 /usr/share/dbus-1/system-services
+103   628    dbus-daemon        -1   2 /lib/dbus-1/system-services
+
+
+The -u option filtering UID:
+
+# ./opensnoop -Uu 1000
+UID   PID    COMM               FD ERR PATH
+1000  30240  ls                  3   0 /etc/ld.so.cache
+1000  30240  ls                  3   0 /lib/x86_64-linux-gnu/libselinux.so.1
+1000  30240  ls                  3   0 /lib/x86_64-linux-gnu/libc.so.6
+1000  30240  ls                  3   0 /lib/x86_64-linux-gnu/libpcre.so.3
+1000  30240  ls                  3   0 /lib/x86_64-linux-gnu/libdl.so.2
+1000  30240  ls                  3   0 /lib/x86_64-linux-gnu/libpthread.so.0
+
 The -x option only prints failed opens:
 
 # ./opensnoop -x
@@ -172,9 +193,11 @@
 optional arguments:
   -h, --help            show this help message and exit
   -T, --timestamp       include timestamp on output
+  -U, --print-uid       include UID on output
   -x, --failed          only show failed opens
   -p PID, --pid PID     trace this PID only
   -t TID, --tid TID     trace this TID only
+  -u UID, --uid UID     trace this UID only
   -d DURATION, --duration DURATION
                         total duration of trace in seconds
   -n NAME, --name NAME  only print process names containing this name
@@ -186,9 +209,11 @@
 examples:
     ./opensnoop           # trace all open() syscalls
     ./opensnoop -T        # include timestamps
+    ./opensnoop -U        # include UID
     ./opensnoop -x        # only show failed opens
     ./opensnoop -p 181    # only trace PID 181
     ./opensnoop -t 123    # only trace TID 123
+    ./opensnoop -u 1000   # only trace UID 1000
     ./opensnoop -d 10     # trace for 10 seconds only
     ./opensnoop -n main   # only print process names containing "main"
     ./opensnoop -e        # show extended fields