On Fri, Jun 12, 2026 at 11:37 PM Andy Lutomirski <[email protected]> wrote:
> > The filter
> > itself is also rather complex (mostly due to needing to account for
> > BPF jump sizes, which differ
> > as different configs (uprobe, uretprobe, SECCOMP_ARCH_COMPAT) have
> > different logic., and I'd worry about
> > keeping logic synced.
>
> Perhaps you and your AI could elaborate? What are these jump sizes?
>
> In any case, I think the actual issue is that the STRICT filter's
> failure case doesn't quite correspond to any of the FILTER actions.
> So maybe it's too complex to be worthwhile.
>
> --Andy
The filter as implemented looks approximately like
load arch
#ifdef SECCOMP_ARCH_COMPAT
if arch == compat: goto check_compat
#endif
if arch != native arch: goto kill
load syscall nr
if syscall == {read/write/exit/sigreturn}: goto allow
#ifdef URETPROBE
if syscall == uretprobe: goto allow
#endif
#ifdef UPROBE
if syscall == uprobe: goto allow
#endif
ret kill
#ifdef SECCOMP_ARCH_COMPAT
check_compat:
if syscall == {read/write/exit/sigreturn}: goto allow
ret kill
#endif
allow:
ret allow
The offsets from each instruction to 'allow' will differ based on the
presence of various options.
I came up with an approach using an enum for numbering each step like so:
> enum {
> SF_LD_ARCH = 0,
> #ifdef SECCOMP_ARCH_COMPAT
> SF_JEQ_COMPAT_ARCH,
> #endif
> SF_JEQ_NATIVE_ARCH,
> /* ... */
> }
> #define SF_REL(from, to) ((__u8)((to) - (from) - 1))
> static const struct sock_filter seccomp_strict_filter[] = {
> [SF_LD_ARCH] = BPF_STMT(...),
> #ifdef SECCOMP_ARCH_COMPAT
> [SF_JEQ_COMPAT_ARCH] = BPF_JUMP(..., SF_REL(SF_JEQ_COMPAT_ARCH,
> SF_LD_NR_COMPAT))
> #endif
> /* ... */
> };
But I'm not convinced it's entirely readable/maintainable.
And just to be clear, I'm not using an AI personally; I was referring
to the Sashiko review bot, which I've now realised does not reply-all
with its reviews.