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):
# self.run_with_int("deadlock_detector.py $(pgrep -n bash)", timeout=10)
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):
self.run_with_int("execsnoop.py")
......
......@@ -73,6 +73,7 @@ enum event_type {
struct data_t {
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];
enum event_type type;
char argv[ARGSIZE];
......@@ -105,7 +106,16 @@ int syscall__execve(struct pt_regs *ctx,
{
// create data here and pass to submit_arg to save stack space (#555)
struct data_t data = {};
struct task_struct *task;
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));
data.type = EVENT_ARG;
......@@ -128,7 +138,16 @@ out:
int do_ret_sys_execve(struct pt_regs *ctx)
{
struct data_t data = {};
struct task_struct *task;
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));
data.type = EVENT_RET;
data.retval = PT_REGS_RC(ctx);
......@@ -160,6 +179,7 @@ ARGSIZE = 128 # should match #define in C above
class Data(ct.Structure):
_fields_ = [
("pid", ct.c_uint),
("ppid", ct.c_uint),
("comm", ct.c_char * TASK_COMM_LEN),
("type", ct.c_int),
("argv", ct.c_char * ARGSIZE),
......@@ -173,9 +193,10 @@ class EventType(object):
start_ts = time.time()
argv = defaultdict(list)
# TODO: 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
# fetching PPID via C when available (#364).
# This is best-effort PPID matching. Short-lived processes may exit
# before we get a chance to read the PPID.
# 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):
try:
with open("/proc/%d/status" % pid) as status:
......@@ -211,7 +232,7 @@ def print_event(cpu, data, size):
if not skip:
if args.timestamp:
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"?"
argv_text = b' '.join(argv[event.pid]).replace(b'\n', b'\\n')
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