]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
bpf: fix loading of BPF_MAXINSNS sized programs
authorDaniel Borkmann <daniel@iogearbox.net>
Wed, 7 Dec 2016 00:15:44 +0000 (01:15 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 7 Dec 2016 18:16:04 +0000 (13:16 -0500)
General assumption is that single program can hold up to BPF_MAXINSNS,
that is, 4096 number of instructions. It is the case with cBPF and
that limit was carried over to eBPF. When recently testing digest, I
noticed that it's actually not possible to feed 4096 instructions
via bpf(2).

The check for > BPF_MAXINSNS was added back then to bpf_check() in
cbd357008604 ("bpf: verifier (add ability to receive verification log)").
However, 09756af46893 ("bpf: expand BPF syscall with program load/unload")
added yet another check that comes before that into bpf_prog_load(),
but this time bails out already in case of >= BPF_MAXINSNS.

Fix it up and perform the check early in bpf_prog_load(), so we can drop
the second one in bpf_check(). It makes sense, because also a 0 insn
program is useless and we don't want to waste any resources doing work
up to bpf_check() point. The existing bpf(2) man page documents E2BIG
as the official error for such cases, so just stick with it as well.

Fixes: 09756af46893 ("bpf: expand BPF syscall with program load/unload")
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
kernel/bpf/syscall.c
kernel/bpf/verifier.c

index c0d2b423ce931e9a0e332fccd3c3e6bd78ba1b22..88f609f1c0c3ad71b40ffc1286800a9bfeb8e7c3 100644 (file)
@@ -786,8 +786,8 @@ static int bpf_prog_load(union bpf_attr *attr)
        /* eBPF programs must be GPL compatible to use GPL-ed functions */
        is_gpl = license_is_gpl_compatible(license);
 
-       if (attr->insn_cnt >= BPF_MAXINSNS)
-               return -EINVAL;
+       if (attr->insn_cnt == 0 || attr->insn_cnt > BPF_MAXINSNS)
+               return -E2BIG;
 
        if (type == BPF_PROG_TYPE_KPROBE &&
            attr->kern_version != LINUX_VERSION_CODE)
index cb37339ca0dac5f282ab3daca0a65a299479b7b9..da9fb2a9b7ebf1fa03dbbd672b21b5a36ea9c2fc 100644 (file)
@@ -3133,9 +3133,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
        struct bpf_verifier_env *env;
        int ret = -EINVAL;
 
-       if ((*prog)->len <= 0 || (*prog)->len > BPF_MAXINSNS)
-               return -E2BIG;
-
        /* 'struct bpf_verifier_env' can be global, but since it's not small,
         * allocate/free it every time bpf_check() is called
         */