Add --uid option to filter by user ID (#3743)
authorevilpan <pangaoshou121@gmail.com>
Fri, 10 Dec 2021 16:58:51 +0000 (00:58 +0800)
committerGitHub <noreply@github.com>
Fri, 10 Dec 2021 16:58:51 +0000 (08:58 -0800)
* Add --uid option to filter by user ID
* update examples and man page of the trace tool

man/man8/trace.8
tools/trace.py
tools/trace_example.txt

index e4f06fc7cc3fa4f0abc3d4d449309f58a62847c7..7afd252764c9933acf11a89074a89645aa1a7b1f 100644 (file)
@@ -2,7 +2,7 @@
 .SH NAME
 trace \- Trace a function and print its arguments or return value, optionally evaluating a filter. Uses Linux eBPF/bcc.
 .SH SYNOPSIS
-.B trace [-h] [-b BUFFER_PAGES] [-p PID] [-L TID] [-v] [-Z STRING_SIZE] [-S] [-s SYM_FILE_LIST]
+.B trace [-h] [-b BUFFER_PAGES] [-p PID] [-L TID] [--uid UID] [-v] [-Z STRING_SIZE] [-S] [-s SYM_FILE_LIST]
          [-M MAX_EVENTS] [-t] [-u] [-T] [-C] [-K] [-U] [-a] [-I header]
          probe [probe ...]
 .SH DESCRIPTION
@@ -24,6 +24,9 @@ Trace only functions in the process PID.
 \-L TID
 Trace only functions in the thread TID.
 .TP
+\--uid UID
+Trace only functions from user UID.
+.TP
 \-v
 Display the generated BPF program, for debugging purposes.
 .TP
@@ -170,9 +173,9 @@ current process' pid and tgid; $uid, $gid to refer to the current user's
 uid and gid; $cpu to refer to the current processor number.
 .SH EXAMPLES
 .TP
-Trace all invocations of the open system call with the name of the file being opened:
+Trace all invocations of the open system call with the name of the file (from userspace) being opened:
 #
-.B trace '::do_sys_open """%s"", arg2'
+.B trace '::do_sys_open """%s"", arg2@user'
 .TP
 Trace all invocations of the read system call where the number of bytes requested is greater than 20,000:
 #
index 40bb32365c565ffd703706df0d78a4e43703038c..0f6d90e8b1a549018a217d10c14e3a97dcbb5aad 100755 (executable)
@@ -37,6 +37,7 @@ class Probe(object):
         print_address = False
         tgid = -1
         pid = -1
+        uid = -1
         page_cnt = None
         build_id_enabled = False
 
@@ -53,6 +54,7 @@ class Probe(object):
                 cls.first_ts_real = time.time()
                 cls.tgid = args.tgid or -1
                 cls.pid = args.pid or -1
+                cls.uid = args.uid or -1
                 cls.page_cnt = args.buffer_pages
                 cls.bin_cmp = args.bin_cmp
                 cls.build_id_enabled = args.sym_file_list is not None
@@ -401,6 +403,7 @@ struct %s
 %s
 %s
 %s
+        u32 uid;
 };
 
 BPF_PERF_OUTPUT(%s);
@@ -485,6 +488,13 @@ BPF_PERF_OUTPUT(%s);
                 else:
                         pid_filter = ""
 
+                if Probe.uid != -1:
+                        uid_filter = """
+        if (__uid != %d) { return 0; }
+                """ % Probe.uid
+                else:
+                        uid_filter = ""
+
                 if self.cgroup_map_name is not None:
                         cgroup_filter = """
         if (%s.check_current_task(0) <= 0) { return 0; }
@@ -530,6 +540,8 @@ BPF_PERF_OUTPUT(%s);
         u64 __pid_tgid = bpf_get_current_pid_tgid();
         u32 __tgid = __pid_tgid >> 32;
         u32 __pid = __pid_tgid; // implicit cast to u32 for bottom half
+        u32 __uid = bpf_get_current_uid_gid();
+        %s
         %s
         %s
         %s
@@ -541,6 +553,7 @@ BPF_PERF_OUTPUT(%s);
         %s
         __data.tgid = __tgid;
         __data.pid = __pid;
+        __data.uid = __uid;
         bpf_get_current_comm(&__data.comm, sizeof(__data.comm));
 %s
 %s
@@ -548,7 +561,7 @@ BPF_PERF_OUTPUT(%s);
         return 0;
 }
 """
-                text = text % (pid_filter, cgroup_filter, prefix,
+                text = text % (pid_filter, uid_filter, cgroup_filter, prefix,
                                self._generate_usdt_filter_read(), self.filter,
                                self.struct_name, time_str, cpu_str, data_fields,
                                stack_trace, self.events_name, ctx_name)
@@ -686,11 +699,17 @@ trace do_sys_open
         Trace the open syscall and print a default trace message when entered
 trace kfree_skb+0x12
         Trace the kfree_skb kernel function after the instruction on the 0x12 offset
-trace 'do_sys_open "%s", arg2'
-        Trace the open syscall and print the filename being opened
-trace 'do_sys_open "%s", arg2' -n main
+trace 'do_sys_open "%s", arg2@user'
+        Trace the open syscall and print the filename. being opened @user is
+        added to arg2 in kprobes to ensure that char * should be copied from
+        the userspace stack to the bpf stack. If not specified, previous
+        behaviour is expected.
+
+trace 'do_sys_open "%s", arg2@user' -n main
         Trace the open syscall and only print event that process names containing "main"
-trace 'do_sys_open "%s", arg2' -f config
+trace 'do_sys_open "%s", arg2@user' --uid 1001
+        Trace the open syscall and only print event that processes with user ID 1001
+trace 'do_sys_open "%s", arg2@user' -f config
         Trace the open syscall and print the filename being opened filtered by "config"
 trace 'sys_read (arg3 > 20000) "read %d bytes", arg3'
         Trace the read syscall and print a message for reads >20000 bytes
@@ -750,6 +769,8 @@ trace -I 'linux/fs_struct.h' 'mntns_install "users = %d", $task->fs->users'
                   dest="tgid", help="id of the process to trace (optional)")
                 parser.add_argument("-L", "--tid", type=int, metavar="TID",
                   dest="pid", help="id of the thread to trace (optional)")
+                parser.add_argument("--uid", type=int, metavar="UID",
+                  dest="uid", help="id of the user to trace (optional)")
                 parser.add_argument("-v", "--verbose", action="store_true",
                   help="print resulting BPF program code before executing")
                 parser.add_argument("-Z", "--string-size", type=int,
index 40c5189a79b1e4c6660654d75d81d6c6385d2b85..36010d61db54177223485798a1297d7a1460f34f 100644 (file)
@@ -337,8 +337,10 @@ PID     TID     COMM            FUNC             -
 
 USAGE message:
 
-usage: trace [-h] [-b BUFFER_PAGES] [-p PID] [-L TID] [-v] [-Z STRING_SIZE]
-             [-S] [-M MAX_EVENTS] [-t] [-T] [-K] [-U] [-a] [-I header]
+usage: trace [-h] [-b BUFFER_PAGES] [-p PID] [-L TID] [--uid UID] [-v]
+             [-Z STRING_SIZE] [-S] [-M MAX_EVENTS] [-t] [-u] [-T] [-C]
+             [-c CGROUP_PATH] [-n NAME] [-f MSG_FILTER] [-B]
+             [-s SYM_FILE_LIST] [-K] [-U] [-a] [-I header]
              probe [probe ...]
 
 Attach to functions and print trace messages.
@@ -353,28 +355,35 @@ optional arguments:
                         (default: 64)
   -p PID, --pid PID     id of the process to trace (optional)
   -L TID, --tid TID     id of the thread to trace (optional)
+  --uid UID             id of the user to trace (optional)
   -v, --verbose         print resulting BPF program code before executing
   -Z STRING_SIZE, --string-size STRING_SIZE
                         maximum size to read from strings
-  -s SYM_FILE_LIST      when collecting stack trace in build id format,
-                        use the coma separated list for symbol resolution
   -S, --include-self    do not filter trace's own pid from the trace
   -M MAX_EVENTS, --max-events MAX_EVENTS
                         number of events to print before quitting
   -t, --timestamp       print timestamp column (offset from trace start)
+  -u, --unix-timestamp  print UNIX timestamp instead of offset from trace
+                        start, requires -t
   -T, --time            print time column
+  -C, --print_cpu       print CPU id
+  -c CGROUP_PATH, --cgroup-path CGROUP_PATH
+                        cgroup path
   -n NAME, --name NAME  only print process names containing this name
   -f MSG_FILTER, --msg-filter MSG_FILTER
-                        only print message of event containing this string
-  -C, --print_cpu       print CPU id
+                        only print the msg of event containing this string
   -B, --bin_cmp         allow to use STRCMP with binary values
+  -s SYM_FILE_LIST, --sym_file_list SYM_FILE_LIST
+                        coma separated list of symbol files to use for symbol
+                        resolution
   -K, --kernel-stack    output kernel stack trace
   -U, --user-stack      output user stack trace
   -a, --address         print virtual address in stacks
   -I header, --include header
                         additional header files to include in the BPF program
-                        as either full path, or relative to current working directory,
-                        or relative to default kernel header search path
+                        as either full path, or relative to current working
+                        directory, or relative to default kernel header search
+                        path
 
 EXAMPLES:
 
@@ -389,6 +398,8 @@ trace 'do_sys_open "%s", arg2@user'
         behaviour is expected.
 trace 'do_sys_open "%s", arg2@user' -n main
         Trace the open syscall and only print event that process names containing "main"
+trace 'do_sys_open "%s", arg2@user' --uid 1001
+        Trace the open syscall and only print event that processes with user ID 1001
 trace 'do_sys_open "%s", arg2@user' -f config
         Trace the open syscall and print the filename being opened filtered by "config"
 trace 'sys_read (arg3 > 20000) "read %d bytes", arg3'