bpf, verifier: further improve search pruning
[cascardo/linux.git] / kernel / bpf / verifier.c
index 2e08f8e..8233021 100644 (file)
@@ -202,6 +202,9 @@ struct verifier_env {
        bool allow_ptr_leaks;
 };
 
+#define BPF_COMPLEXITY_LIMIT_INSNS     65536
+#define BPF_COMPLEXITY_LIMIT_STACK     1024
+
 /* verbose verifier prints what it's seeing
  * bpf_check() is called under lock, so no race to access these global vars
  */
@@ -454,7 +457,7 @@ static struct verifier_state *push_stack(struct verifier_env *env, int insn_idx,
        elem->next = env->head;
        env->head = elem;
        env->stack_size++;
-       if (env->stack_size > 1024) {
+       if (env->stack_size > BPF_COMPLEXITY_LIMIT_STACK) {
                verbose("BPF program is too complex\n");
                goto err;
        }
@@ -652,8 +655,12 @@ static int check_ctx_access(struct verifier_env *env, int off, int size,
                            enum bpf_access_type t)
 {
        if (env->prog->aux->ops->is_valid_access &&
-           env->prog->aux->ops->is_valid_access(off, size, t))
+           env->prog->aux->ops->is_valid_access(off, size, t)) {
+               /* remember the offset of last byte accessed in ctx */
+               if (env->prog->aux->max_ctx_offset < off + size)
+                       env->prog->aux->max_ctx_offset = off + size;
                return 0;
+       }
 
        verbose("invalid bpf_context access off=%d size=%d\n", off, size);
        return -EACCES;
@@ -1539,6 +1546,8 @@ peek_stack:
                                goto peek_stack;
                        else if (ret < 0)
                                goto err_free;
+                       if (t + 1 < insn_cnt)
+                               env->explored_states[t + 1] = STATE_LIST_MARK;
                } else if (opcode == BPF_JA) {
                        if (BPF_SRC(insns[t].code) != BPF_K) {
                                ret = -EINVAL;
@@ -1743,7 +1752,7 @@ static int do_check(struct verifier_env *env)
                insn = &insns[insn_idx];
                class = BPF_CLASS(insn->code);
 
-               if (++insn_processed > 32768) {
+               if (++insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) {
                        verbose("BPF program is too large. Proccessed %d insn\n",
                                insn_processed);
                        return -E2BIG;