Skip to content

Commit 62d5d2b

Browse files
tyhicksmheon
authored andcommitted
golang: Add API level bindings
Add bindings for getting and setting the libseccomp API level which was added in the following libseccomp commit: commit e89d18205c7dcd7582f41051cd6389c9b12dfccf Author: Paul Moore <[email protected]> Date: Thu Sep 21 10:27:38 2017 -0400 api: create an API level construct as part of the supported API The added tests for getting and setting the API level detect if API level support is available in libseccomp and tests the behavior of GetApi() and SetApi() accordingly. Signed-off-by: Tyler Hicks <[email protected]> Signed-off-by: Matthew Heon <[email protected]>
1 parent f6ec81d commit 62d5d2b

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

seccomp.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,25 @@ func GetLibraryVersion() (major, minor, micro uint) {
328328
return verMajor, verMinor, verMicro
329329
}
330330

331+
// GetApi returns the API level supported by the system.
332+
// Returns a positive int containing the API level, or 0 with an error if the
333+
// API level could not be detected due to the library being older than v2.4.0.
334+
// See the seccomp_api_get(3) man page for details on available API levels:
335+
// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
336+
func GetApi() (uint, error) {
337+
return getApi()
338+
}
339+
340+
// SetApi forcibly sets the API level. General use of this function is strongly
341+
// discouraged.
342+
// Returns an error if the API level could not be set. An error is always
343+
// returned if the library is older than v2.4.0
344+
// See the seccomp_api_get(3) man page for details on available API levels:
345+
// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3
346+
func SetApi(api uint) error {
347+
return setApi(api)
348+
}
349+
331350
// Syscall functions
332351

333352
// GetName retrieves the name of a syscall from its number.

seccomp_internal.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616

1717
// #cgo pkg-config: libseccomp
1818
/*
19+
#include <errno.h>
1920
#include <stdlib.h>
2021
#include <seccomp.h>
2122
@@ -122,6 +123,25 @@ unsigned int get_micro_version()
122123
}
123124
#endif
124125
126+
// The libseccomp API level functions were added in v2.4.0
127+
#if (SCMP_VER_MAJOR < 2) || \
128+
(SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4)
129+
const unsigned int seccomp_api_get(void)
130+
{
131+
// libseccomp-golang requires libseccomp v2.2.0, at a minimum, which
132+
// supported API level 2. However, the kernel may not support API level
133+
// 2 constructs which are the seccomp() system call and the TSYNC
134+
// filter flag. Return the "reserved" value of 0 here to indicate that
135+
// proper API level support is not available in libseccomp.
136+
return 0;
137+
}
138+
139+
int seccomp_api_set(unsigned int level)
140+
{
141+
return -EOPNOTSUPP;
142+
}
143+
#endif
144+
125145
typedef struct scmp_arg_cmp* scmp_cast_t;
126146
127147
void* make_arg_cmp_array(unsigned int length)
@@ -201,6 +221,29 @@ func ensureSupportedVersion() error {
201221
return nil
202222
}
203223

224+
// Get the API level
225+
func getApi() (uint, error) {
226+
api := C.seccomp_api_get()
227+
if api == 0 {
228+
return 0, fmt.Errorf("API level operations are not supported")
229+
}
230+
231+
return uint(api), nil
232+
}
233+
234+
// Set the API level
235+
func setApi(api uint) error {
236+
if retCode := C.seccomp_api_set(C.uint(api)); retCode != 0 {
237+
if syscall.Errno(-1*retCode) == syscall.EOPNOTSUPP {
238+
return fmt.Errorf("API level operations are not supported")
239+
}
240+
241+
return fmt.Errorf("could not set API level: %v", retCode)
242+
}
243+
244+
return nil
245+
}
246+
204247
// Filter helpers
205248

206249
// Filter finalizer - ensure that kernel context for filters is freed

seccomp_test.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,51 @@ func TestVersionError(t *testing.T) {
6464
}
6565
}
6666

67+
func ApiLevelIsSupported() bool {
68+
return verMajor > 2 ||
69+
(verMajor == 2 && verMinor > 3) ||
70+
(verMajor == 2 && verMinor == 3 && verMicro >= 3)
71+
}
72+
73+
func TestGetApiLevel(t *testing.T) {
74+
api, err := GetApi()
75+
if !ApiLevelIsSupported() {
76+
if api != 0 {
77+
t.Errorf("API level returned despite lack of support: %v", api)
78+
} else if err == nil {
79+
t.Errorf("No error returned despite lack of API level support")
80+
}
81+
82+
t.Skipf("Skipping test: %s", err)
83+
} else if err != nil {
84+
t.Errorf("Error getting API level: %s", err)
85+
}
86+
fmt.Printf("Got API level of %v\n", api)
87+
}
88+
89+
func TestSetApiLevel(t *testing.T) {
90+
var expectedApi uint
91+
92+
expectedApi = 1
93+
err := SetApi(expectedApi)
94+
if !ApiLevelIsSupported() {
95+
if err == nil {
96+
t.Errorf("No error returned despite lack of API level support")
97+
}
98+
99+
t.Skipf("Skipping test: %s", err)
100+
} else if err != nil {
101+
t.Errorf("Error setting API level: %s", err)
102+
}
103+
104+
api, err := GetApi()
105+
if err != nil {
106+
t.Errorf("Error getting API level: %s", err)
107+
} else if api != expectedApi {
108+
t.Errorf("Got API level %v: expected %v", api, expectedApi)
109+
}
110+
}
111+
67112
func TestActionSetReturnCode(t *testing.T) {
68113
if ActInvalid.SetReturnCode(0x0010) != ActInvalid {
69114
t.Errorf("Able to set a return code on invalid action!")

0 commit comments

Comments
 (0)