Commit f86f7e84 authored by Paul Chaignon's avatar Paul Chaignon Committed by yonghong-song

Skip dereferences inside bpf_probe_reads calls (#1824)

* Skip all dereferences inside bpf_probe_read calls

If the user decides to rely on a manual call to bpf_probe_read, we
don't try to rewrite its last argument.  This is needed as the
rewriter starts to recognize and rewrite more and more dereferences.

* tools: fix dereferences following 1a765a17
parent 37f7fef2
......@@ -281,10 +281,7 @@ bool ProbeVisitor::VisitCallExpr(CallExpr *Call) {
if (VarDecl *V = dyn_cast<VarDecl>(Call->getCalleeDecl())) {
if (V->getName() == "bpf_probe_read" && Call->getNumArgs() >= 3) {
const Expr *E = Call->getArg(2)->IgnoreParenCasts();
if (const UnaryOperator *UnaryExpr = dyn_cast<UnaryOperator>(E)) {
if (UnaryExpr->getOpcode() == UO_AddrOf)
whitelist_.insert(E);
}
whitelist_.insert(E);
return true;
}
}
......
......@@ -94,8 +94,9 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req)
data.len = req->__data_len;
data.sector = req->__sector;
bpf_probe_read(&data.name, sizeof(data.name), valp->name);
struct gendisk *rq_disk = req->rq_disk;
bpf_probe_read(&data.disk_name, sizeof(data.disk_name),
req->rq_disk->disk_name);
rq_disk->disk_name);
}
/*
......
......@@ -84,14 +84,14 @@ int trace_unlink(struct pt_regs *ctx, struct inode *dir, struct dentry *dentry)
delta = (bpf_ktime_get_ns() - *tsp) / 1000000;
birth.delete(&dentry);
if (dentry->d_name.len == 0)
struct qstr d_name = dentry->d_name;
if (d_name.len == 0)
return 0;
if (bpf_get_current_comm(&data.comm, sizeof(data.comm)) == 0) {
data.pid = pid;
data.delta = delta;
bpf_probe_read(&data.fname, sizeof(data.fname),
(void *)dentry->d_name.name);
bpf_probe_read(&data.fname, sizeof(data.fname), d_name.name);
}
events.perf_submit(ctx, &data, sizeof(data));
......
......@@ -111,8 +111,9 @@ static int trace_rw_entry(struct pt_regs *ctx, struct file *file,
val.sz = count;
val.ts = bpf_ktime_get_ns();
val.name_len = de->d_name.len;
bpf_probe_read(&val.name, sizeof(val.name), (void *)de->d_name.name);
struct qstr d_name = de->d_name;
val.name_len = d_name.len;
bpf_probe_read(&val.name, sizeof(val.name), d_name.name);
bpf_get_current_comm(&val.comm, sizeof(val.comm));
entryinfo.update(&pid, &val);
......
......@@ -100,14 +100,15 @@ static int do_entry(struct pt_regs *ctx, struct file *file,
// skip I/O lacking a filename
struct dentry *de = file->f_path.dentry;
int mode = file->f_inode->i_mode;
if (de->d_name.len == 0 || TYPE_FILTER)
struct qstr d_name = de->d_name;
if (d_name.len == 0 || TYPE_FILTER)
return 0;
// store counts and sizes by pid & file
struct info_t info = {.pid = pid};
bpf_get_current_comm(&info.comm, sizeof(info.comm));
info.name_len = de->d_name.len;
bpf_probe_read(&info.name, sizeof(info.name), (void *)de->d_name.name);
info.name_len = d_name.len;
bpf_probe_read(&info.name, sizeof(info.name), d_name.name);
if (S_ISREG(mode)) {
info.type = 'R';
} else if (S_ISSOCK(mode)) {
......
......@@ -44,11 +44,11 @@ int kprobe__md_flush_request(struct pt_regs *ctx, void *mddev, struct bio *bio)
* and maintenance burden.
*/
#ifdef bio_dev
bpf_probe_read(&data.disk, sizeof(data.disk), bio->bi_disk->disk_name);
struct gendisk *bi_disk = bio->bi_disk;
#else
bpf_probe_read(&data.disk, sizeof(data.disk),
bio->bi_bdev->bd_disk->disk_name);
struct gendisk *bi_disk = bio->bi_bdev->bd_disk;
#endif
bpf_probe_read(&data.disk, sizeof(data.disk), bi_disk->disk_name);
events.perf_submit(ctx, &data, sizeof(data));
return 0;
}
......
......@@ -87,7 +87,8 @@ BPF_HASH(counts, struct info_t, struct val_t);
int kprobe__kmem_cache_alloc(struct pt_regs *ctx, struct kmem_cache *cachep)
{
struct info_t info = {};
bpf_probe_read(&info.name, sizeof(info.name), (void *)cachep->name);
const char *name = cachep->name;
bpf_probe_read(&info.name, sizeof(info.name), name);
struct val_t *valp, zero = {};
valp = counts.lookup_or_init(&info, &zero);
......
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