Merge tag 'mmc-v3.18-1' of git://git.linaro.org/people/ulf.hansson/mmc
[firefly-linux-kernel-4.4.55.git] / kernel / bpf / syscall.c
index 0afb4eaa1887e71002e247789c1333adf203350c..ba61c8c160321ea6f333c560a9dc1e55f8b83632 100644 (file)
@@ -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)
 {
@@ -424,7 +458,7 @@ struct bpf_prog *bpf_prog_get(u32 ufd)
 }
 
 /* last field in 'union bpf_attr' used by this command */
-#define        BPF_PROG_LOAD_LAST_FIELD license
+#define        BPF_PROG_LOAD_LAST_FIELD log_buf
 
 static int bpf_prog_load(union bpf_attr *attr)
 {
@@ -473,11 +507,14 @@ static int bpf_prog_load(union bpf_attr *attr)
                goto free_prog;
 
        /* run eBPF verifier */
-       /* err = bpf_check(prog, tb); */
+       err = bpf_check(prog, 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);