helper/seccomp: implement reader interface via pipe
All checks were successful
Test / Create distribution (push) Successful in 1m6s
Test / Run NixOS test (push) Successful in 2m44s

This also does not require the libc tmpfile call.

BPF programs emitted by libseccomp seems to be deterministic. The tests would catch regressions as it verifies the program against known good output backed by manual testing.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
2025-02-03 18:10:29 +09:00
parent d58fb8c6ee
commit 5b7b3fa9a4
4 changed files with 237 additions and 16 deletions

51
helper/seccomp/api.go Normal file
View File

@@ -0,0 +1,51 @@
package seccomp
import (
"errors"
"io"
"os"
"syscall"
)
func Export(opts SyscallOpts) (f *os.File, err error) {
if f, err = tmpfile(); err != nil {
return
}
if err = exportFilter(f.Fd(), opts); err != nil {
return
}
_, err = f.Seek(0, io.SeekStart)
return
}
/*
An Encoder writes a BPF program to an output stream.
Methods of Encoder are not safe for concurrent use.
An Encoder must not be copied after first use.
*/
type Encoder struct {
*exporter
}
func (e *Encoder) Read(p []byte) (n int, err error) {
if err = e.prepare(); err != nil {
return
}
return e.r.Read(p)
}
func (e *Encoder) Close() error {
if e.r == nil {
return syscall.EINVAL
}
// this hangs if the cgo thread fails to exit
return errors.Join(e.closeWrite(), <-e.exportErr)
}
// New returns an inactive Encoder instance.
func New(opts SyscallOpts) *Encoder {
return &Encoder{newExporter(opts)}
}