Commit 719e1003 authored by Paul Chaignon's avatar Paul Chaignon Committed by Brenden Blanco

Trace external pointers from helpers

At this time, a single helper can return a kernel pointer,
bpf_get_current_task.
parent 4d450bab
...@@ -77,6 +77,9 @@ class ProbeChecker : public RecursiveASTVisitor<ProbeChecker> { ...@@ -77,6 +77,9 @@ class ProbeChecker : public RecursiveASTVisitor<ProbeChecker> {
} }
bool VisitCallExpr(CallExpr *E) { bool VisitCallExpr(CallExpr *E) {
needs_probe_ = false; needs_probe_ = false;
if (VarDecl *V = dyn_cast<VarDecl>(E->getCalleeDecl())) {
needs_probe_ = V->getName() == "bpf_get_current_task";
}
return false; return false;
} }
bool VisitParenExpr(ParenExpr *E) { bool VisitParenExpr(ParenExpr *E) {
......
...@@ -4,10 +4,11 @@ ...@@ -4,10 +4,11 @@
from bcc import BPF from bcc import BPF
import ctypes as ct import ctypes as ct
from unittest import main, TestCase from unittest import main, skipUnless, TestCase
import os import os
import sys import sys
from contextlib import contextmanager from contextlib import contextmanager
import distutils.version
@contextmanager @contextmanager
def redirect_stderr(to): def redirect_stderr(to):
...@@ -21,6 +22,17 @@ def redirect_stderr(to): ...@@ -21,6 +22,17 @@ def redirect_stderr(to):
sys.stderr.flush() sys.stderr.flush()
os.dup2(copied.fileno(), stderr_fd) 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): class TestClang(TestCase):
def test_complex(self): def test_complex(self):
b = BPF(src_file="test_clang_complex.c", debug=0) b = BPF(src_file="test_clang_complex.c", debug=0)
...@@ -454,6 +466,18 @@ int dns_test(struct __sk_buff *skb) { ...@@ -454,6 +466,18 @@ int dns_test(struct __sk_buff *skb) {
""" """
b = BPF(text=text) 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): def test_unary_operator(self):
text = """ text = """
#include <linux/fs.h> #include <linux/fs.h>
......
...@@ -144,8 +144,8 @@ int do_perf_event(struct bpf_perf_event_data *ctx) ...@@ -144,8 +144,8 @@ int do_perf_event(struct bpf_perf_event_data *ctx)
struct task_struct *task = NULL; struct task_struct *task = NULL;
struct cfs_rq_partial *my_q = NULL; struct cfs_rq_partial *my_q = NULL;
task = (struct task_struct *)bpf_get_current_task(); task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&my_q, sizeof(my_q), &task->se.cfs_rq); my_q = (struct cfs_rq_partial *)task->se.cfs_rq;
bpf_probe_read(&len, sizeof(len), &my_q->nr_running); len = my_q->nr_running;
struct data_t data = {.ts = now, .cpu = cpu, .len = len}; struct data_t data = {.ts = now, .cpu = cpu, .len = len};
events.perf_submit(ctx, &data, sizeof(data)); events.perf_submit(ctx, &data, sizeof(data));
......
...@@ -104,10 +104,9 @@ int kprobe__sys_mount(struct pt_regs *ctx, char __user *source, ...@@ -104,10 +104,9 @@ int kprobe__sys_mount(struct pt_regs *ctx, char __user *source,
bpf_get_current_comm(event.enter.comm, sizeof(event.enter.comm)); bpf_get_current_comm(event.enter.comm, sizeof(event.enter.comm));
event.enter.flags = flags; event.enter.flags = flags;
task = (struct task_struct *)bpf_get_current_task(); task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&nsproxy, sizeof(nsproxy), &task->nsproxy); nsproxy = task->nsproxy;
bpf_probe_read(&mnt_ns, sizeof(mnt_ns), &nsproxy->mnt_ns); mnt_ns = nsproxy->mnt_ns;
bpf_probe_read(&event.enter.mnt_ns, sizeof(event.enter.mnt_ns), event.enter.mnt_ns = mnt_ns->ns.inum;
&mnt_ns->ns.inum);
events.perf_submit(ctx, &event, sizeof(event)); events.perf_submit(ctx, &event, sizeof(event));
event.type = EVENT_MOUNT_SOURCE; event.type = EVENT_MOUNT_SOURCE;
...@@ -160,10 +159,9 @@ int kprobe__sys_umount(struct pt_regs *ctx, char __user *target, int flags) ...@@ -160,10 +159,9 @@ int kprobe__sys_umount(struct pt_regs *ctx, char __user *target, int flags)
bpf_get_current_comm(event.enter.comm, sizeof(event.enter.comm)); bpf_get_current_comm(event.enter.comm, sizeof(event.enter.comm));
event.enter.flags = flags; event.enter.flags = flags;
task = (struct task_struct *)bpf_get_current_task(); task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&nsproxy, sizeof(nsproxy), &task->nsproxy); nsproxy = task->nsproxy;
bpf_probe_read(&mnt_ns, sizeof(mnt_ns), &nsproxy->mnt_ns); mnt_ns = nsproxy->mnt_ns;
bpf_probe_read(&event.enter.mnt_ns, sizeof(event.enter.mnt_ns), event.enter.mnt_ns = mnt_ns->ns.inum;
&mnt_ns->ns.inum);
events.perf_submit(ctx, &event, sizeof(event)); events.perf_submit(ctx, &event, sizeof(event));
event.type = EVENT_UMOUNT_TARGET; event.type = EVENT_UMOUNT_TARGET;
......
...@@ -81,8 +81,8 @@ int do_perf_event() ...@@ -81,8 +81,8 @@ int do_perf_event()
// of BPF will support task_rq(p) or something similar as a more reliable // of BPF will support task_rq(p) or something similar as a more reliable
// interface. // interface.
task = (struct task_struct *)bpf_get_current_task(); task = (struct task_struct *)bpf_get_current_task();
bpf_probe_read(&my_q, sizeof(my_q), &task->se.cfs_rq); my_q = (struct cfs_rq_partial *)task->se.cfs_rq;
bpf_probe_read(&len, sizeof(len), &my_q->nr_running); len = my_q->nr_running;
// Calculate run queue length by subtracting the currently running task, // Calculate run queue length by subtracting the currently running task,
// if present. len 0 == idle, len 1 == one running task. // if present. len 0 == idle, len 1 == one running task.
......
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