diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2ba9875..4220255 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,7 +16,7 @@ jobs: fail-fast: false matrix: go-version: [1.22.x, 1.23.x] - libseccomp: ["v2.3.3", "v2.4.4", "v2.5.5", "HEAD"] + libseccomp: ["v2.3.3", "v2.4.4", "v2.5.6", "v2.6.0", "HEAD"] steps: diff --git a/seccomp.go b/seccomp.go index ab64c4a..e362ec6 100644 --- a/seccomp.go +++ b/seccomp.go @@ -961,6 +961,25 @@ func (f *ScmpFilter) GetRawRC() (bool, error) { return true, nil } +// GetWaitKill returns the current state of WaitKill flag, +// or an error if an issue was encountered retrieving the value. +// See SetWaitKill for more details. +func (f *ScmpFilter) GetWaitKill() (bool, error) { + val, err := f.getFilterAttr(filterAttrWaitKill) + if err != nil { + if e := checkAPI("GetWaitKill", 7, 2, 6, 0); e != nil { + err = e + } + + return false, err + } + if val == 0 { + return false, nil + } + + return true, nil +} + // SetBadArchAction sets the default action taken on a syscall for an // architecture not in the filter, or an error if an issue was encountered // setting the value. @@ -1073,6 +1092,25 @@ func (f *ScmpFilter) SetRawRC(state bool) error { return err } +// SetWaitKill sets whether libseccomp should request wait killable semantics +// when possible. Defaults to false. +func (f *ScmpFilter) SetWaitKill(state bool) error { + var toSet C.uint32_t = 0x0 + + if state { + toSet = 0x1 + } + + err := f.setFilterAttr(filterAttrWaitKill, toSet) + if err != nil { + if e := checkAPI("SetWaitKill", 7, 2, 6, 0); e != nil { + err = e + } + } + + return err +} + // SetSyscallPriority sets a syscall's priority. // This provides a hint to the filter generator in libseccomp about the // importance of this syscall. High-priority syscalls are placed diff --git a/seccomp_internal.go b/seccomp_internal.go index fe3e4cb..859b710 100644 --- a/seccomp_internal.go +++ b/seccomp_internal.go @@ -148,6 +148,11 @@ const uint32_t C_ACT_NOTIFY = SCMP_ACT_NOTIFY; #define SCMP_FLTATR_API_SYSRAWRC _SCMP_FLTATR_MIN #endif +// Added in libseccomp v2.6.0. +#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 6 +#define SCMP_FLTATR_CTL_WAITKILL _SCMP_FLTATR_MIN +#endif + const uint32_t C_ATTRIBUTE_DEFAULT = (uint32_t)SCMP_FLTATR_ACT_DEFAULT; const uint32_t C_ATTRIBUTE_BADARCH = (uint32_t)SCMP_FLTATR_ACT_BADARCH; const uint32_t C_ATTRIBUTE_NNP = (uint32_t)SCMP_FLTATR_CTL_NNP; @@ -156,6 +161,7 @@ const uint32_t C_ATTRIBUTE_LOG = (uint32_t)SCMP_FLTATR_CTL_LOG; const uint32_t C_ATTRIBUTE_SSB = (uint32_t)SCMP_FLTATR_CTL_SSB; const uint32_t C_ATTRIBUTE_OPTIMIZE = (uint32_t)SCMP_FLTATR_CTL_OPTIMIZE; const uint32_t C_ATTRIBUTE_SYSRAWRC = (uint32_t)SCMP_FLTATR_API_SYSRAWRC; +const uint32_t C_ATTRIBUTE_WAITKILL = (uint32_t)SCMP_FLTATR_CTL_WAITKILL; const int C_CMP_NE = (int)SCMP_CMP_NE; const int C_CMP_LT = (int)SCMP_CMP_LT; @@ -283,6 +289,7 @@ const ( filterAttrSSB filterAttrOptimize filterAttrRawRC + filterAttrWaitKill ) const ( @@ -709,6 +716,8 @@ func (a scmpFilterAttr) toNative() uint32 { return uint32(C.C_ATTRIBUTE_OPTIMIZE) case filterAttrRawRC: return uint32(C.C_ATTRIBUTE_SYSRAWRC) + case filterAttrWaitKill: + return uint32(C.C_ATTRIBUTE_WAITKILL) default: return 0x0 } diff --git a/seccomp_test.go b/seccomp_test.go index 3e2b5ff..44b104e 100644 --- a/seccomp_test.go +++ b/seccomp_test.go @@ -503,6 +503,24 @@ func TestFilterAttributeGettersAndSetters(t *testing.T) { } else if rawrc != true { t.Error("RawRC flag was not set correctly") } + + // Checks that require API level >= 7 and libseccomp >= 2.6.0. + if err := checkAPI(t.Name(), 7, 2, 6, 0); err != nil { + t.Logf("Skipping the rest of the test: %v", err) + return + } + + err = filter.SetWaitKill(true) + if err != nil { + t.Errorf("Error setting WaitKill flag: %v", err) + } + + wk, err := filter.GetWaitKill() + if err != nil { + t.Errorf("Error getting WaitKill flag: %v", err) + } else if wk != true { + t.Error("WaitKill flag was not set correctly") + } } func TestMergeFilters(t *testing.T) {