Skip to content

Commit

Permalink
Trace external pointers from helpers
Browse files Browse the repository at this point in the history
At this time, a single helper can return a kernel pointer,
bpf_get_current_task.
  • Loading branch information
pchaigno authored and drzaeus77 committed Aug 23, 2017
1 parent 4d450ba commit 719e100
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 13 deletions.
3 changes: 3 additions & 0 deletions src/cc/frontends/clang/b_frontend_action.cc
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ class ProbeChecker : public RecursiveASTVisitor<ProbeChecker> {
}
bool VisitCallExpr(CallExpr *E) {
needs_probe_ = false;
if (VarDecl *V = dyn_cast<VarDecl>(E->getCalleeDecl())) {
needs_probe_ = V->getName() == "bpf_get_current_task";
}
return false;
}
bool VisitParenExpr(ParenExpr *E) {
Expand Down
26 changes: 25 additions & 1 deletion tests/python/test_clang.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

from bcc import BPF
import ctypes as ct
from unittest import main, TestCase
from unittest import main, skipUnless, TestCase
import os
import sys
from contextlib import contextmanager
import distutils.version

@contextmanager
def redirect_stderr(to):
Expand All @@ -21,6 +22,17 @@ def redirect_stderr(to):
sys.stderr.flush()
os.dup2(copied.fileno(), stderr_fd)

def kernel_version_ge(major, minor):
# True if running kernel is >= X.Y
version = distutils.version.LooseVersion(os.uname()[2]).version
if version[0] > major:
return True
if version[0] < major:
return False
if minor and version[1] < minor:
return False
return True

class TestClang(TestCase):
def test_complex(self):
b = BPF(src_file="test_clang_complex.c", debug=0)
Expand Down Expand Up @@ -454,6 +466,18 @@ def test_bpf_dins_pkt_rewrite(self):
"""
b = BPF(text=text)

@skipUnless(kernel_version_ge(4,8), "requires kernel >= 4.8")
def test_ext_ptr_from_helper(self):
text = """
#include <linux/sched.h>
int test(struct pt_regs *ctx) {
struct task_struct *task = (struct task_struct *)bpf_get_current_task();
return task->prio;
}
"""
b = BPF(text=text)
fn = b.load_func("test", BPF.KPROBE)

def test_unary_operator(self):
text = """
#include <linux/fs.h>
Expand Down
4 changes: 2 additions & 2 deletions tools/cpuunclaimed.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@
struct task_struct *task = NULL;
struct cfs_rq_partial *my_q = NULL;
task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&my_q, sizeof(my_q), &task->se.cfs_rq);
bpf_probe_read(&len, sizeof(len), &my_q->nr_running);
my_q = (struct cfs_rq_partial *)task->se.cfs_rq;
len = my_q->nr_running;
struct data_t data = {.ts = now, .cpu = cpu, .len = len};
events.perf_submit(ctx, &data, sizeof(data));
Expand Down
14 changes: 6 additions & 8 deletions tools/mountsnoop.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,9 @@
bpf_get_current_comm(event.enter.comm, sizeof(event.enter.comm));
event.enter.flags = flags;
task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&nsproxy, sizeof(nsproxy), &task->nsproxy);
bpf_probe_read(&mnt_ns, sizeof(mnt_ns), &nsproxy->mnt_ns);
bpf_probe_read(&event.enter.mnt_ns, sizeof(event.enter.mnt_ns),
&mnt_ns->ns.inum);
nsproxy = task->nsproxy;
mnt_ns = nsproxy->mnt_ns;
event.enter.mnt_ns = mnt_ns->ns.inum;
events.perf_submit(ctx, &event, sizeof(event));
event.type = EVENT_MOUNT_SOURCE;
Expand Down Expand Up @@ -160,10 +159,9 @@
bpf_get_current_comm(event.enter.comm, sizeof(event.enter.comm));
event.enter.flags = flags;
task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&nsproxy, sizeof(nsproxy), &task->nsproxy);
bpf_probe_read(&mnt_ns, sizeof(mnt_ns), &nsproxy->mnt_ns);
bpf_probe_read(&event.enter.mnt_ns, sizeof(event.enter.mnt_ns),
&mnt_ns->ns.inum);
nsproxy = task->nsproxy;
mnt_ns = nsproxy->mnt_ns;
event.enter.mnt_ns = mnt_ns->ns.inum;
events.perf_submit(ctx, &event, sizeof(event));
event.type = EVENT_UMOUNT_TARGET;
Expand Down
4 changes: 2 additions & 2 deletions tools/runqlen.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@
// of BPF will support task_rq(p) or something similar as a more reliable
// interface.
task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&my_q, sizeof(my_q), &task->se.cfs_rq);
bpf_probe_read(&len, sizeof(len), &my_q->nr_running);
my_q = (struct cfs_rq_partial *)task->se.cfs_rq;
len = my_q->nr_running;
// Calculate run queue length by subtracting the currently running task,
// if present. len 0 == idle, len 1 == one running task.
Expand Down

0 comments on commit 719e100

Please sign in to comment.