Commit 5965fdc2 authored by Brendan Gregg's avatar Brendan Gregg Committed by GitHub

Merge pull request #1885 from calavera/execsnoop_real_parent

[tools/execsnoop] Try to get parent PID from current task's real parent.
parents 2f64bf0b d46f4f40
...@@ -144,7 +144,7 @@ class SmokeTests(TestCase): ...@@ -144,7 +144,7 @@ class SmokeTests(TestCase):
# self.run_with_int("deadlock_detector.py $(pgrep -n bash)", timeout=10) # self.run_with_int("deadlock_detector.py $(pgrep -n bash)", timeout=10)
pass pass
@skipUnless(kernel_version_ge(4,4), "requires kernel >= 4.4") @skipUnless(kernel_version_ge(4,8), "requires kernel >= 4.8")
def test_execsnoop(self): def test_execsnoop(self):
self.run_with_int("execsnoop.py") self.run_with_int("execsnoop.py")
......
...@@ -73,6 +73,7 @@ enum event_type { ...@@ -73,6 +73,7 @@ enum event_type {
struct data_t { struct data_t {
u32 pid; // PID as in the userspace term (i.e. task->tgid in kernel) u32 pid; // PID as in the userspace term (i.e. task->tgid in kernel)
u32 ppid; // Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel)
char comm[TASK_COMM_LEN]; char comm[TASK_COMM_LEN];
enum event_type type; enum event_type type;
char argv[ARGSIZE]; char argv[ARGSIZE];
...@@ -105,7 +106,16 @@ int syscall__execve(struct pt_regs *ctx, ...@@ -105,7 +106,16 @@ int syscall__execve(struct pt_regs *ctx,
{ {
// create data here and pass to submit_arg to save stack space (#555) // create data here and pass to submit_arg to save stack space (#555)
struct data_t data = {}; struct data_t data = {};
struct task_struct *task;
data.pid = bpf_get_current_pid_tgid() >> 32; data.pid = bpf_get_current_pid_tgid() >> 32;
task = (struct task_struct *)bpf_get_current_task();
// Some kernels, like Ubuntu 4.13.0-generic, return 0
// as the real_parent->tgid.
// We use the get_ppid function as a fallback in those cases. (#1883)
data.ppid = task->real_parent->tgid;
bpf_get_current_comm(&data.comm, sizeof(data.comm)); bpf_get_current_comm(&data.comm, sizeof(data.comm));
data.type = EVENT_ARG; data.type = EVENT_ARG;
...@@ -128,7 +138,16 @@ out: ...@@ -128,7 +138,16 @@ out:
int do_ret_sys_execve(struct pt_regs *ctx) int do_ret_sys_execve(struct pt_regs *ctx)
{ {
struct data_t data = {}; struct data_t data = {};
struct task_struct *task;
data.pid = bpf_get_current_pid_tgid() >> 32; data.pid = bpf_get_current_pid_tgid() >> 32;
task = (struct task_struct *)bpf_get_current_task();
// Some kernels, like Ubuntu 4.13.0-generic, return 0
// as the real_parent->tgid.
// We use the get_ppid function as a fallback in those cases. (#1883)
data.ppid = task->real_parent->tgid;
bpf_get_current_comm(&data.comm, sizeof(data.comm)); bpf_get_current_comm(&data.comm, sizeof(data.comm));
data.type = EVENT_RET; data.type = EVENT_RET;
data.retval = PT_REGS_RC(ctx); data.retval = PT_REGS_RC(ctx);
...@@ -160,6 +179,7 @@ ARGSIZE = 128 # should match #define in C above ...@@ -160,6 +179,7 @@ ARGSIZE = 128 # should match #define in C above
class Data(ct.Structure): class Data(ct.Structure):
_fields_ = [ _fields_ = [
("pid", ct.c_uint), ("pid", ct.c_uint),
("ppid", ct.c_uint),
("comm", ct.c_char * TASK_COMM_LEN), ("comm", ct.c_char * TASK_COMM_LEN),
("type", ct.c_int), ("type", ct.c_int),
("argv", ct.c_char * ARGSIZE), ("argv", ct.c_char * ARGSIZE),
...@@ -173,9 +193,10 @@ class EventType(object): ...@@ -173,9 +193,10 @@ class EventType(object):
start_ts = time.time() start_ts = time.time()
argv = defaultdict(list) argv = defaultdict(list)
# TODO: This is best-effort PPID matching. Short-lived processes may exit # This is best-effort PPID matching. Short-lived processes may exit
# before we get a chance to read the PPID. This should be replaced with # before we get a chance to read the PPID.
# fetching PPID via C when available (#364). # This is a fallback for when fetching the PPID from task->real_parent->tgip
# returns 0, which happens in some kernel versions.
def get_ppid(pid): def get_ppid(pid):
try: try:
with open("/proc/%d/status" % pid) as status: with open("/proc/%d/status" % pid) as status:
...@@ -211,7 +232,7 @@ def print_event(cpu, data, size): ...@@ -211,7 +232,7 @@ def print_event(cpu, data, size):
if not skip: if not skip:
if args.timestamp: if args.timestamp:
print("%-8.3f" % (time.time() - start_ts), end="") print("%-8.3f" % (time.time() - start_ts), end="")
ppid = get_ppid(event.pid) ppid = event.ppid if event.ppid > 0 else get_ppid(event.pid)
ppid = b"%d" % ppid if ppid > 0 else b"?" ppid = b"%d" % ppid if ppid > 0 else b"?"
argv_text = b' '.join(argv[event.pid]).replace(b'\n', b'\\n') argv_text = b' '.join(argv[event.pid]).replace(b'\n', b'\\n')
printb(b"%-16s %-6d %-6s %3d %s" % (event.comm, event.pid, printb(b"%-16s %-6d %-6s %3d %s" % (event.comm, event.pid,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment