]> git.karo-electronics.de Git - linux-beck.git/commitdiff
samples/seccomp: Support programs with >256 instructions
authorRicky Zhou <rickyz@chromium.org>
Thu, 13 Oct 2016 17:37:28 +0000 (10:37 -0700)
committerKees Cook <keescook@chromium.org>
Tue, 1 Nov 2016 15:58:17 +0000 (08:58 -0700)
Previously, the program size was incorrectly truncated to 8 bits,
resulting in broken labels in large programs. Also changes the jump
resolution loop to not rely on undefined behavior (making a pointer
point before the filter array).

Signed-off-by: Ricky Zhou <rickyz@chromium.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
samples/seccomp/bpf-helper.c

index 05cb4d5ff9f5bef632baa98eb687f1781dcb5e5e..1ef0f4d72898d9945a95fd78b501583fb18d1093 100644 (file)
 int bpf_resolve_jumps(struct bpf_labels *labels,
                      struct sock_filter *filter, size_t count)
 {
-       struct sock_filter *begin = filter;
-       __u8 insn = count - 1;
+       size_t i;
 
-       if (count < 1)
+       if (count < 1 || count > BPF_MAXINSNS)
                return -1;
        /*
        * Walk it once, backwards, to build the label table and do fixups.
        * Since backward jumps are disallowed by BPF, this is easy.
        */
-       filter += insn;
-       for (; filter >= begin; --insn, --filter) {
-               if (filter->code != (BPF_JMP+BPF_JA))
+       for (i = 0; i < count; ++i) {
+               size_t offset = count - i - 1;
+               struct sock_filter *instr = &filter[offset];
+               if (instr->code != (BPF_JMP+BPF_JA))
                        continue;
-               switch ((filter->jt<<8)|filter->jf) {
+               switch ((instr->jt<<8)|instr->jf) {
                case (JUMP_JT<<8)|JUMP_JF:
-                       if (labels->labels[filter->k].location == 0xffffffff) {
+                       if (labels->labels[instr->k].location == 0xffffffff) {
                                fprintf(stderr, "Unresolved label: '%s'\n",
-                                       labels->labels[filter->k].label);
+                                       labels->labels[instr->k].label);
                                return 1;
                        }
-                       filter->k = labels->labels[filter->k].location -
-                                   (insn + 1);
-                       filter->jt = 0;
-                       filter->jf = 0;
+                       instr->k = labels->labels[instr->k].location -
+                                   (offset + 1);
+                       instr->jt = 0;
+                       instr->jf = 0;
                        continue;
                case (LABEL_JT<<8)|LABEL_JF:
-                       if (labels->labels[filter->k].location != 0xffffffff) {
+                       if (labels->labels[instr->k].location != 0xffffffff) {
                                fprintf(stderr, "Duplicate label use: '%s'\n",
-                                       labels->labels[filter->k].label);
+                                       labels->labels[instr->k].label);
                                return 1;
                        }
-                       labels->labels[filter->k].location = insn;
-                       filter->k = 0; /* fall through */
-                       filter->jt = 0;
-                       filter->jf = 0;
+                       labels->labels[instr->k].location = offset;
+                       instr->k = 0; /* fall through */
+                       instr->jt = 0;
+                       instr->jf = 0;
                        continue;
                }
        }