Skip to content

Commit e8d905a

Browse files
committed
Add filter.Precompute
Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent da2d32e commit e8d905a

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

seccomp.go

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,18 @@ import (
1717
"unsafe"
1818
)
1919

20-
// #include <stdlib.h>
21-
// #include <seccomp.h>
20+
/*
21+
#include <errno.h>
22+
#include <stdlib.h>
23+
#include <seccomp.h>
24+
25+
// The following functions were added in libseccomp v2.6.0.
26+
#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 6
27+
int seccomp_precompute(scmp_filter_ctx ctx) {
28+
return -EOPNOTSUPP;
29+
}
30+
#endif
31+
*/
2232
import "C"
2333

2434
// Exported types
@@ -818,6 +828,26 @@ func (f *ScmpFilter) RemoveArch(arch ScmpArch) error {
818828
return nil
819829
}
820830

831+
// Precompute precomputes the seccomp filter for later use by [Load] and
832+
// similar functions. Not only does this improve performance of [Load],
833+
// it also ensures that the seccomp filter can be loaded in an
834+
// async-signal-safe manner if no changes have been made to the filter
835+
// since it was precomputed.
836+
func (f *ScmpFilter) Precompute() error {
837+
f.lock.Lock()
838+
defer f.lock.Unlock()
839+
840+
if !f.valid {
841+
return errBadFilter
842+
}
843+
844+
if retCode := C.seccomp_precompute(f.filterCtx); retCode != 0 {
845+
return errRc(retCode)
846+
}
847+
848+
return nil
849+
}
850+
821851
// Load loads a filter context into the kernel.
822852
// Returns an error if the filter context is invalid or the syscall failed.
823853
func (f *ScmpFilter) Load() error {

seccomp_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package seccomp
44

55
import (
6+
"errors"
67
"fmt"
78
"os"
89
"os/exec"
@@ -601,6 +602,18 @@ func TestRuleAddAndLoad(t *testing.T) {
601602
}
602603

603604
func subprocessRuleAddAndLoad(t *testing.T) {
605+
doSubprocessRuleAddAndLoad(t, false)
606+
}
607+
608+
func TestRuleAddPrecomputeAndLoad(t *testing.T) {
609+
execInSubprocess(t, subprocessRuleAddPrecomputeAndLoad)
610+
}
611+
612+
func subprocessRuleAddPrecomputeAndLoad(t *testing.T) {
613+
doSubprocessRuleAddAndLoad(t, true)
614+
}
615+
616+
func doSubprocessRuleAddAndLoad(t *testing.T, precompute bool) {
604617
// Test #1: Add a trivial filter
605618
filter1, err := NewFilter(ActAllow)
606619
if err != nil {
@@ -653,6 +666,19 @@ func subprocessRuleAddAndLoad(t *testing.T) {
653666
t.Errorf("Error adding second conditional rule: %s", err)
654667
}
655668

669+
if precompute {
670+
expErr := error(nil)
671+
// Precompute needs seccomp 2.6.0 and API level 7.
672+
if checkAPI(t.Name(), 7, 2, 6, 0) != nil {
673+
expErr = syscall.EOPNOTSUPP
674+
}
675+
676+
err = filter1.Precompute()
677+
if !errors.Is(err, expErr) {
678+
t.Errorf("Precompute: want %v, got %v", expErr, err)
679+
}
680+
}
681+
656682
err = filter1.Load()
657683
if err != nil {
658684
t.Errorf("Error loading filter: %s", err)

0 commit comments

Comments
 (0)