[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210929235910.1765396-12-jevburton.kernel@gmail.com>
Date: Wed, 29 Sep 2021 23:59:08 +0000
From: Joe Burton <jevburton.kernel@...il.com>
To: Alexei Starovoitov <ast@...nel.org>,
Daniel Borkmann <daniel@...earbox.net>,
Andrii Nakryiko <andrii@...nel.org>,
Martin KaFai Lau <kafai@...com>
Cc: Song Liu <songliubraving@...com>, Yonghong Song <yhs@...com>,
John Fastabend <john.fastabend@...il.com>,
KP Singh <kpsingh@...nel.org>,
Petar Penkov <ppenkov@...gle.com>,
Stanislav Fomichev <sdf@...gle.com>,
Hao Luo <haoluo@...gle.com>, netdev@...r.kernel.org,
bpf@...r.kernel.org, Joe Burton <jevburton@...gle.com>
Subject: [RFC PATCH v2 11/13] bpf: verifier inserts map tracing helper call
From: Joe Burton <jevburton@...gle.com>
The verifier will automatically insert a map tracing helper call after
each bpf_map_{update,delete}_elem(). Registers are preserved
appropriately to make this transparent to applications.
Signed-off-by: Joe Burton <jevburton@...gle.com>
---
kernel/bpf/verifier.c | 75 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 70 insertions(+), 5 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index babcb135dc0d..01a99571ecea 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -12678,6 +12678,48 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env,
return 0;
}
+int get_map_tracing_patchlet(
+ void *map_func,
+ void *map_trace_func,
+ const int nregs,
+ struct bpf_prog *prog,
+ struct bpf_insn *insn_buf,
+ int *extra_stack)
+{
+ const int stack_offset = -1 * (int16_t) prog->aux->stack_depth;
+ const int reg_size_bytes = 8;
+ int cnt = 0, i;
+
+ /* push args onto the stack so that we can invoke the tracer after */
+ for (i = 0; i < nregs; i++)
+ insn_buf[cnt++] = BPF_STX_MEM(
+ BPF_DW, BPF_REG_FP,
+ BPF_REG_1 + i,
+ stack_offset - (i + 1) * reg_size_bytes);
+
+ insn_buf[cnt++] = BPF_EMIT_CALL(map_func);
+
+ for (i = 0; i < nregs; i++)
+ insn_buf[cnt++] = BPF_LDX_MEM(
+ BPF_DW, BPF_REG_1 + i,
+ BPF_REG_FP,
+ stack_offset - (i + 1) * reg_size_bytes);
+
+ /* save return code from map update */
+ insn_buf[cnt++] = BPF_STX_MEM(BPF_DW, BPF_REG_FP, BPF_REG_0,
+ stack_offset - reg_size_bytes);
+
+ /* invoke tracing helper */
+ insn_buf[cnt++] = BPF_EMIT_CALL(map_trace_func);
+
+ /* restore return code from map update */
+ insn_buf[cnt++] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_FP,
+ stack_offset - reg_size_bytes);
+
+ *extra_stack = max_t(int, *extra_stack, nregs * reg_size_bytes);
+ return cnt;
+}
+
/* Do various post-verification rewrites in a single program pass.
* These rewrites simplify JIT and interpreter implementations.
*/
@@ -12694,7 +12736,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
struct bpf_insn insn_buf[16];
struct bpf_prog *new_prog;
struct bpf_map *map_ptr;
- int i, ret, cnt, delta = 0;
+ int i, ret, cnt, delta = 0, extra_stack = 0;
for (i = 0; i < insn_cnt; i++, insn++) {
/* Make divide-by-zero exceptions impossible. */
@@ -12998,11 +13040,23 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
insn->imm = BPF_CALL_IMM(ops->map_lookup_elem);
continue;
case BPF_FUNC_map_update_elem:
- insn->imm = BPF_CALL_IMM(ops->map_update_elem);
- continue;
+ cnt = get_map_tracing_patchlet(
+ ops->map_update_elem,
+ bpf_trace_map_update_elem,
+ /*nregs=*/4, prog, insn_buf,
+ &extra_stack);
+ if (cnt < 0)
+ return cnt;
+ goto patch_map_ops_tracing;
case BPF_FUNC_map_delete_elem:
- insn->imm = BPF_CALL_IMM(ops->map_delete_elem);
- continue;
+ cnt = get_map_tracing_patchlet(
+ ops->map_delete_elem,
+ bpf_trace_map_delete_elem,
+ /*nregs=*/2, prog, insn_buf,
+ &extra_stack);
+ if (cnt < 0)
+ return cnt;
+ goto patch_map_ops_tracing;
case BPF_FUNC_map_push_elem:
insn->imm = BPF_CALL_IMM(ops->map_push_elem);
continue;
@@ -13018,6 +13072,16 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
}
goto patch_call_imm;
+patch_map_ops_tracing:
+ new_prog = bpf_patch_insn_data(env, i + delta,
+ insn_buf, cnt);
+ if (!new_prog)
+ return -ENOMEM;
+
+ delta += cnt - 1;
+ env->prog = prog = new_prog;
+ insn = new_prog->insnsi + i + delta;
+ continue;
}
/* Implement bpf_jiffies64 inline. */
@@ -13092,6 +13156,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
}
sort_kfunc_descs_by_imm(env->prog);
+ prog->aux->stack_depth += extra_stack;
return 0;
}
--
2.33.0.685.g46640cef36-goog
Powered by blists - more mailing lists