|
@@ -357,6 +357,40 @@ void bpf_register_prog_type(struct bpf_prog_type_list *tl)
|
|
|
list_add(&tl->list_node, &bpf_prog_types);
|
|
|
}
|
|
|
|
|
|
+/* fixup insn->imm field of bpf_call instructions:
|
|
|
+ * if (insn->imm == BPF_FUNC_map_lookup_elem)
|
|
|
+ * insn->imm = bpf_map_lookup_elem - __bpf_call_base;
|
|
|
+ * else if (insn->imm == BPF_FUNC_map_update_elem)
|
|
|
+ * insn->imm = bpf_map_update_elem - __bpf_call_base;
|
|
|
+ * else ...
|
|
|
+ *
|
|
|
+ * this function is called after eBPF program passed verification
|
|
|
+ */
|
|
|
+static void fixup_bpf_calls(struct bpf_prog *prog)
|
|
|
+{
|
|
|
+ const struct bpf_func_proto *fn;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < prog->len; i++) {
|
|
|
+ struct bpf_insn *insn = &prog->insnsi[i];
|
|
|
+
|
|
|
+ if (insn->code == (BPF_JMP | BPF_CALL)) {
|
|
|
+ /* we reach here when program has bpf_call instructions
|
|
|
+ * and it passed bpf_check(), means that
|
|
|
+ * ops->get_func_proto must have been supplied, check it
|
|
|
+ */
|
|
|
+ BUG_ON(!prog->aux->ops->get_func_proto);
|
|
|
+
|
|
|
+ fn = prog->aux->ops->get_func_proto(insn->imm);
|
|
|
+ /* all functions that have prototype and verifier allowed
|
|
|
+ * programs to call them, must be real in-kernel functions
|
|
|
+ */
|
|
|
+ BUG_ON(!fn->func);
|
|
|
+ insn->imm = fn->func - __bpf_call_base;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* drop refcnt on maps used by eBPF program and free auxilary data */
|
|
|
static void free_used_maps(struct bpf_prog_aux *aux)
|
|
|
{
|
|
@@ -478,6 +512,9 @@ static int bpf_prog_load(union bpf_attr *attr)
|
|
|
if (err < 0)
|
|
|
goto free_used_maps;
|
|
|
|
|
|
+ /* fixup BPF_CALL->imm field */
|
|
|
+ fixup_bpf_calls(prog);
|
|
|
+
|
|
|
/* eBPF program is ready to be JITed */
|
|
|
bpf_prog_select_runtime(prog);
|
|
|
|