Seccomp filter: BPF program
Paul Chaignon
paul.chaignon at gmail.com
Tue Apr 9 05:23:50 UTC 2019
Hi Chen,
I have rebased your work [1] from last GSoC and run it locally. It works
and does reduce overhead significantly!
I have also dumped the BPF program for a very small example (cf. below).
Did I miss something or will the last comparison for the arch (line 30)
never be made? If it matches X86_64, it looks like it will go from line 2
to line 3 and hit RET_ALLOW or RET_TRACE.
I'm also not sure I understand your check lines 7--10. Is that aimed to
give control to the userspace tracer whenever the x32 ABI is used? If so,
why are lines 30--39 still required?
Did you consider other algorithms to match syscall numbers with BPF? I
was considering binary search and bit matching. I don't think binary
search would improve the number of instructions, but it should improve the
runtime for large filters. With bit matching, I was thinking we could
encode filtered syscalls in a bit array (implemented as a sequence of
32bit values) at construction-time, then bitwise AND 1 << (nr % 32)
against the appropriate portion of the bit array (selected with nr / 32).
Would love to have your opinion.
Cheers,
Paul
1 - https://github.com/pchaigno/strace/commits/ppiao-seccomp
$ strace -n -d -ebpf ls >/dev/null
Dumped BPF program:
1: STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, arch))
2: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 11, AUDIT_ARCH_X86_64)
3: STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, nr))
4: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 8, 0, 59)
5: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 1, 321)
6: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 6, 323)
7: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 2, __X32_SYSCALL_BIT)
8: STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, arch))
9: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 3, 0, AUDIT_ARCH_X86_64)
10: STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, nr))
11: JUMP(BPF_JMP + BPF_JGE + BPF_K, 1, 0, 335)
12: STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW)
13: STMT(BPF_RET + BPF_K, SECCOMP_RET_TRACE)
14: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 15, AUDIT_ARCH_I386)
15: STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, nr))
16: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 12, 0, 11)
17: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 11, 0, 102)
18: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 10, 0, 117)
19: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 1, 222)
20: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 8, 224)
21: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 7, 0, 251)
22: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 6, 0, 285)
23: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 1, 357)
24: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 4, 359)
25: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 1, 387)
26: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 2, 546)
27: JUMP(BPF_JMP + BPF_JGE + BPF_K, 1, 0, 546)
28: STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW)
29: STMT(BPF_RET + BPF_K, SECCOMP_RET_TRACE)
30: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 0, 9, AUDIT_ARCH_X86_64)
31: STMT(BPF_LD + BPF_W + BPF_ABS, offsetof(struct seccomp_data, nr))
32: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 6, 0, 1073742145)
33: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 1, 1073742159)
34: JUMP(BPF_JMP + BPF_JGE + BPF_K, 0, 4, 1073742336)
35: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 3, 0, 1073742344)
36: JUMP(BPF_JMP + BPF_JEQ + BPF_K, 2, 0, 1073742369)
37: JUMP(BPF_JMP + BPF_JGE + BPF_K, 1, 0, 1073742372)
38: STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW)
39: STMT(BPF_RET + BPF_K, SECCOMP_RET_TRACE)
40: STMT(BPF_RET + BPF_K, SECCOMP_RET_TRACE)
Equivalent pseudo-code:
if (arch == AUDIT_ARCH_X86_64) {
if (nr == 59)
return SECCOMP_RET_TRACE;
if (nr >= 321 && nr <= 323)
return SECCOMP_RET_TRACE;
if (nr >= __X32_SYSCALL_BIT && arch == AUDIT_ARCH_X86_64)
return SECCOMP_RET_TRACE;
if (nr == 335)
return SECCOMP_RET_TRACE;
return SECCOMP_RET_ALLOW;
}
if (arch == AUDIT_ARCH_I386) {
if (nr == 11 || nr == 102 || nr == 117)
return SECCOMP_RET_TRACE;
if (nr >= 222 && nr <= 224)
return SECCOMP_RET_TRACE;
if (nr == 251 || nr == 285)
return SECCOMP_RET_TRACE;
if (nr >= 357 && nr <= 359)
return SECCOMP_RET_TRACE;
if (nr >= 387 && nr <= 546)
return SECCOMP_RET_TRACE;
if (nr >= 546)
return SECCOMP_RET_TRACE;
return SECCOMP_RET_ALLOW;
}
if (arch == AUDIT_ARCH_X86_64) {
if (nr == 1073742145)
return SECCOMP_RET_TRACE;
if (nr >= 1073742159 && nr <= 1073742336)
return SECCOMP_RET_TRACE;
if (nr == 1073742344 || nr == 1073742369)
return SECCOMP_RET_TRACE;
if (nr >= 1073742372)
return SECCOMP_RET_TRACE;
return SECCOMP_RET_ALLOW;
}
return SECCOMP_RET_ALLOW;
More information about the Strace-devel
mailing list