From: Matthew Heon <[email protected]>

Go's extensive use of threading makes installing Seccomp filters
without TSync set have strong potential for unexpected
behavior. Setting TSync unconditionally ensures expected behavior.
This commit bumps the minimum supported library version to v2.2.0
to ensure support for TSync.

Signed-off-by: Matthew Heon <[email protected]>
---
 seccomp.go          | 60 ++++++++++-------------------------------------------
 seccomp_internal.go | 58 +++++----------------------------------------------
 seccomp_test.go     |  4 ++--
 3 files changed, 18 insertions(+), 104 deletions(-)

diff --git a/seccomp.go b/seccomp.go
index 11c6afd..d3d9e6b 100644
--- a/seccomp.go
+++ b/seccomp.go
@@ -43,7 +43,7 @@ func (e VersionError) Error() string {
        if e.minimum != "" {
                format += e.minimum + ": "
        } else {
-               format += "2.1.0: "
+               format += "2.2.0: "
        }
        format += "detected %d.%d.%d"
        return fmt.Sprintf(format, verMajor, verMinor, verMicro)
@@ -76,8 +76,8 @@ type ScmpSyscall int32
 
 const (
        // Valid architectures recognized by libseccomp
-       // ARM64 and all MIPS architectures are unsupported by versions of the
-       // library before v2.2 and will return errors if used
+       // PowerPC and S390(x) architectures are unavailable below library 
version
+       // v2.3.0 and will returns errors if used with incompatible libraries
 
        // ArchInvalid is a placeholder to ensure uninitialized ScmpArch
        // variables are invalid
@@ -494,6 +494,13 @@ func NewFilter(defaultAction ScmpAction) (*ScmpFilter, 
error) {
        filter.valid = true
        runtime.SetFinalizer(filter, filterFinalizer)
 
+       // Enable TSync so all goroutines will receive the same rules
+       // If the kernel does not support TSYNC, allow us to continue without 
error
+       if err := filter.setFilterAttr(filterAttrTsync, 0x1); err != nil && err 
!= syscall.ENOTSUP {
+               filter.Release()
+               return nil, fmt.Errorf("could not create filter - error setting 
tsync bit: %v", err)
+       }
+
        return filter, nil
 }
 
@@ -550,7 +557,7 @@ func (f *ScmpFilter) Release() {
 // The source filter src will be released as part of the process, and will no
 // longer be usable or valid after this call.
 // To be merged, filters must NOT share any architectures, and all their
-// attributes (Default Action, Bad Arch Action, No New Privs and TSync bools)
+// attributes (Default Action, Bad Arch Action, and No New Privs bools)
 // must match.
 // The filter src will be merged into the filter this is called on.
 // The architectures of the src filter not present in the destination, and all
@@ -723,30 +730,6 @@ func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) {
        return true, nil
 }
 
-// GetTsyncBit returns whether Thread Synchronization will be enabled on the
-// filter being loaded, or an error if an issue was encountered retrieving the
-// value.
-// Thread Sync ensures that all members of the thread group of the calling
-// process will share the same Seccomp filter set.
-// Tsync is a fairly recent addition to the Linux kernel and older kernels
-// lack support. If the running kernel does not support Tsync and it is
-// requested in a filter, Libseccomp will not enable TSync support and will
-// proceed as normal.
-// This function is unavailable before v2.2 of libseccomp and will return an
-// error.
-func (f *ScmpFilter) GetTsyncBit() (bool, error) {
-       tSync, err := f.getFilterAttr(filterAttrTsync)
-       if err != nil {
-               return false, err
-       }
-
-       if tSync == 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.
@@ -773,27 +756,6 @@ func (f *ScmpFilter) SetNoNewPrivsBit(state bool) error {
        return f.setFilterAttr(filterAttrNNP, toSet)
 }
 
-// SetTsync sets whether Thread Synchronization will be enabled on the filter
-// being loaded. Returns an error if setting Tsync failed, or the filter is
-// invalid.
-// Thread Sync ensures that all members of the thread group of the calling
-// process will share the same Seccomp filter set.
-// Tsync is a fairly recent addition to the Linux kernel and older kernels
-// lack support. If the running kernel does not support Tsync and it is
-// requested in a filter, Libseccomp will not enable TSync support and will
-// proceed as normal.
-// This function is unavailable before v2.2 of libseccomp and will return an
-// error.
-func (f *ScmpFilter) SetTsync(enable bool) error {
-       var toSet C.uint32_t = 0x0
-
-       if enable {
-               toSet = 0x1
-       }
-
-       return f.setFilterAttr(filterAttrTsync, toSet)
-}
-
 // 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 5a99ce6..c9fd616 100644
--- a/seccomp_internal.go
+++ b/seccomp_internal.go
@@ -20,43 +20,15 @@ import (
 #include <seccomp.h>
 
 #if SCMP_VER_MAJOR < 2
-#error Minimum supported version of Libseccomp is v2.1.0
-#elif SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 1
-#error Minimum supported version of Libseccomp is v2.1.0
+#error Minimum supported version of Libseccomp is v2.2.0
+#elif SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 2
+#error Minimum supported version of Libseccomp is v2.2.0
 #endif
 
 #define ARCH_BAD ~0
 
 const uint32_t C_ARCH_BAD = ARCH_BAD;
 
-#ifndef SCMP_ARCH_AARCH64
-#define SCMP_ARCH_AARCH64 ARCH_BAD
-#endif
-
-#ifndef SCMP_ARCH_MIPS
-#define SCMP_ARCH_MIPS ARCH_BAD
-#endif
-
-#ifndef SCMP_ARCH_MIPS64
-#define SCMP_ARCH_MIPS64 ARCH_BAD
-#endif
-
-#ifndef SCMP_ARCH_MIPS64N32
-#define SCMP_ARCH_MIPS64N32 ARCH_BAD
-#endif
-
-#ifndef SCMP_ARCH_MIPSEL
-#define SCMP_ARCH_MIPSEL ARCH_BAD
-#endif
-
-#ifndef SCMP_ARCH_MIPSEL64
-#define SCMP_ARCH_MIPSEL64 ARCH_BAD
-#endif
-
-#ifndef SCMP_ARCH_MIPSEL64N32
-#define SCMP_ARCH_MIPSEL64N32 ARCH_BAD
-#endif
-
 #ifndef SCMP_ARCH_PPC
 #define SCMP_ARCH_PPC ARCH_BAD
 #endif
@@ -101,12 +73,6 @@ const uint32_t C_ACT_ERRNO         = SCMP_ACT_ERRNO(0);
 const uint32_t C_ACT_TRACE         = SCMP_ACT_TRACE(0);
 const uint32_t C_ACT_ALLOW         = SCMP_ACT_ALLOW;
 
-// If TSync is not supported, make sure it doesn't map to a supported filter 
attribute
-// Don't worry about major version < 2, the minimum version checks should 
catch that case
-#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 2
-#define SCMP_FLTATR_CTL_TSYNC _SCMP_CMP_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;
@@ -219,9 +185,9 @@ func checkVersionAbove(major, minor, micro uint) bool {
                (verMajor == major && verMinor == minor && verMicro >= micro)
 }
 
-// Ensure that the library is supported, i.e. >= 2.1.0.
+// Ensure that the library is supported, i.e. >= 2.2.0.
 func ensureSupportedVersion() error {
-       if !checkVersionAbove(2, 1, 0) {
+       if !checkVersionAbove(2, 2, 0) {
                return VersionError{}
        }
        return nil
@@ -243,13 +209,6 @@ func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) 
(C.uint32_t, error) {
                return 0x0, errBadFilter
        }
 
-       if !checkVersionAbove(2, 2, 0) && attr == filterAttrTsync {
-               return 0x0, VersionError{
-                       message: "thread synchronization attribute is not 
supported",
-                       minimum: "2.2.0",
-               }
-       }
-
        var attribute C.uint32_t
 
        retCode := C.seccomp_attr_get(f.filterCtx, attr.toNative(), &attribute)
@@ -269,13 +228,6 @@ func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, 
value C.uint32_t) error
                return errBadFilter
        }
 
-       if !checkVersionAbove(2, 2, 0) && attr == filterAttrTsync {
-               return VersionError{
-                       message: "thread synchronization attribute is not 
supported",
-                       minimum: "2.2.0",
-               }
-       }
-
        retCode := C.seccomp_attr_set(f.filterCtx, attr.toNative(), value)
        if retCode != 0 {
                return syscall.Errno(-1 * retCode)
diff --git a/seccomp_test.go b/seccomp_test.go
index fc66ed5..92e9eba 100644
--- a/seccomp_test.go
+++ b/seccomp_test.go
@@ -42,7 +42,7 @@ var versionErrorTests = []versionErrorTest{
                        "",
                },
                "Libseccomp version too low: " +
-                       "deadbeef: minimum supported is 2.1.0: " +
+                       "deadbeef: minimum supported is 2.2.0: " +
                        "detected " + versionStr,
        },
        {
@@ -50,7 +50,7 @@ var versionErrorTests = []versionErrorTest{
                        "",
                        "",
                },
-               "Libseccomp version too low: minimum supported is 2.1.0: " +
+               "Libseccomp version too low: minimum supported is 2.2.0: " +
                        "detected " + versionStr,
        },
 }
-- 
2.9.3

-- 
You received this message because you are subscribed to the Google Groups 
"libseccomp" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to