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