Search code examples
csystem-callsbpfseccomp

BPF: How to set the jump value as the value stored in the accumulator?


I am working with seccomp BPF and need to set the jump values (jt/jf/k) of a jump statement (conditional jump/jump always) as the value stored in the accumulator. Is this possible? I have a hunch that it is not, because the BPF verifier cannot check the jump values before loading the filter. If not, are there any workarounds?

struct sock_filter filter = 
  {
    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),
    BPF_STMT(BPF_JMP | BPF_JA, /* Value stored in the accumulator */),
    ...
  }

I tried looking here but I couldn't figure out any way to do it. My knowledge of BPF is also rather elementary and only within the purview of seccomp. Can you help me? Thanks for your time.


Solution

  • No, BPF doesn't support indirect branch instructions. Neither cBPF as used in seccomp-bpf nor eBPF does.


    In the case of cBPF, you can check this in the documentation. You will see that instructions are defined as:

    struct sock_filter { /* Filter block */
        __u16   code;    /* Actual filter code */
        __u8    jt;      /* Jump true */
        __u8    jf;      /* Jump false */
        __u32   k;       /* Generic multiuse field */
    };
    

    where jt, jf, and k can be interpreted as the jump offset depending on the specific jump instruction being used. In all cases, they are interpreted as immediate values and not register numbers:

       6               L                    Jump label L
       7               #k,Lt,Lf             Jump to Lt if true, otherwise jump to Lf
       8               x/%x,Lt,Lf           Jump to Lt if true, otherwise jump to Lf
       9               #k,Lt                Jump to Lt if predicate is true
      10               x/%x,Lt              Jump to Lt if predicate is true