full diff: https://github.com/seccomp/libseccomp-golang/compare/32f571b70023028bd57d9288c20efbcb237f3ce0...689e3c1541a84461afc49c1c87352a6cedf72e9c
Release notes:
* Version 0.9.1 - May 21, 2019
- Minimum supported version of libseccomp bumped to v2.2.0
- Use Libseccomp's `seccomp_version` API to retrieve library version
- Unconditionally set TSync attribute for filters, due to Go's heavily threaded nature
- Fix CVE-2017-18367 - Multiple syscall arguments were incorrectly combined with logical-OR, instead of logical-AND
- Fix a failure to build on Debian-based distributions due to CGo code
- Fix unit test failures on 32-bit architectures
- Improve several errors to be more verbose about their causes
- Add support for SCMP_ACT_LOG (with libseccomp versions 2.4.x and higher), permitting syscalls but logging their execution
- Add support for SCMP_FLTATR_CTL_LOG (with libseccomp versions 2.4.x and higher), logging not-allowed actions when they are denied
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
| ... | ... |
@@ -83,7 +83,7 @@ google.golang.org/grpc 25c4f928eaa6d96443009bd84238 |
| 83 | 83 |
github.com/opencontainers/runc 425e105d5a03fabd737a126ad93d62a9eeede87f # v1.0.0-rc8 |
| 84 | 84 |
github.com/opencontainers/runtime-spec 29686dbc5559d93fb1ef402eeda3e35c38d75af4 # v1.0.1-59-g29686db |
| 85 | 85 |
github.com/opencontainers/image-spec d60099175f88c47cd379c4738d158884749ed235 # v1.0.1 |
| 86 |
-github.com/seccomp/libseccomp-golang 32f571b70023028bd57d9288c20efbcb237f3ce0 |
|
| 86 |
+github.com/seccomp/libseccomp-golang 689e3c1541a84461afc49c1c87352a6cedf72e9c # v0.9.1 |
|
| 87 | 87 |
|
| 88 | 88 |
# libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json) |
| 89 | 89 |
github.com/coreos/go-systemd 39ca1b05acc7ad1220e09f133283b8859a8b71ab # v17 |
| ... | ... |
@@ -24,3 +24,28 @@ please note that a Google account is not required to subscribe to the mailing |
| 24 | 24 |
list. |
| 25 | 25 |
|
| 26 | 26 |
-> https://groups.google.com/d/forum/libseccomp |
| 27 |
+ |
|
| 28 |
+Documentation is also available at: |
|
| 29 |
+ |
|
| 30 |
+ -> https://godoc.org/github.com/seccomp/libseccomp-golang |
|
| 31 |
+ |
|
| 32 |
+* Installing the package |
|
| 33 |
+ |
|
| 34 |
+The libseccomp-golang bindings require at least Go v1.2.1 and GCC v4.8.4; |
|
| 35 |
+earlier versions may yield unpredictable results. If you meet these |
|
| 36 |
+requirements you can install this package using the command below: |
|
| 37 |
+ |
|
| 38 |
+ $ go get github.com/seccomp/libseccomp-golang |
|
| 39 |
+ |
|
| 40 |
+* Testing the Library |
|
| 41 |
+ |
|
| 42 |
+A number of tests and lint related recipes are provided in the Makefile, if |
|
| 43 |
+you want to run the standard regression tests, you can excute the following: |
|
| 44 |
+ |
|
| 45 |
+ $ make check |
|
| 46 |
+ |
|
| 47 |
+In order to execute the 'make lint' recipe the 'golint' tool is needed, it |
|
| 48 |
+can be found at: |
|
| 49 |
+ |
|
| 50 |
+ -> https://github.com/golang/lint |
|
| 51 |
+ |
| ... | ... |
@@ -27,6 +27,28 @@ import "C" |
| 27 | 27 |
|
| 28 | 28 |
// Exported types |
| 29 | 29 |
|
| 30 |
+// VersionError denotes that the system libseccomp version is incompatible |
|
| 31 |
+// with this package. |
|
| 32 |
+type VersionError struct {
|
|
| 33 |
+ message string |
|
| 34 |
+ minimum string |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func (e VersionError) Error() string {
|
|
| 38 |
+ format := "Libseccomp version too low: " |
|
| 39 |
+ if e.message != "" {
|
|
| 40 |
+ format += e.message + ": " |
|
| 41 |
+ } |
|
| 42 |
+ format += "minimum supported is " |
|
| 43 |
+ if e.minimum != "" {
|
|
| 44 |
+ format += e.minimum + ": " |
|
| 45 |
+ } else {
|
|
| 46 |
+ format += "2.2.0: " |
|
| 47 |
+ } |
|
| 48 |
+ format += "detected %d.%d.%d" |
|
| 49 |
+ return fmt.Sprintf(format, verMajor, verMinor, verMicro) |
|
| 50 |
+} |
|
| 51 |
+ |
|
| 30 | 52 |
// ScmpArch represents a CPU architecture. Seccomp can restrict syscalls on a |
| 31 | 53 |
// per-architecture basis. |
| 32 | 54 |
type ScmpArch uint |
| ... | ... |
@@ -54,8 +76,8 @@ type ScmpSyscall int32 |
| 54 | 54 |
|
| 55 | 55 |
const ( |
| 56 | 56 |
// Valid architectures recognized by libseccomp |
| 57 |
- // ARM64 and all MIPS architectures are unsupported by versions of the |
|
| 58 |
- // library before v2.2 and will return errors if used |
|
| 57 |
+ // PowerPC and S390(x) architectures are unavailable below library version |
|
| 58 |
+ // v2.3.0 and will returns errors if used with incompatible libraries |
|
| 59 | 59 |
|
| 60 | 60 |
// ArchInvalid is a placeholder to ensure uninitialized ScmpArch |
| 61 | 61 |
// variables are invalid |
| ... | ... |
@@ -115,6 +137,10 @@ const ( |
| 115 | 115 |
ActTrace ScmpAction = iota |
| 116 | 116 |
// ActAllow permits the syscall to continue execution |
| 117 | 117 |
ActAllow ScmpAction = iota |
| 118 |
+ // ActLog permits the syscall to continue execution after logging it. |
|
| 119 |
+ // This action is only usable when libseccomp API level 3 or higher is |
|
| 120 |
+ // supported. |
|
| 121 |
+ ActLog ScmpAction = iota |
|
| 118 | 122 |
) |
| 119 | 123 |
|
| 120 | 124 |
const ( |
| ... | ... |
@@ -151,6 +177,10 @@ const ( |
| 151 | 151 |
// GetArchFromString returns an ScmpArch constant from a string representing an |
| 152 | 152 |
// architecture |
| 153 | 153 |
func GetArchFromString(arch string) (ScmpArch, error) {
|
| 154 |
+ if err := ensureSupportedVersion(); err != nil {
|
|
| 155 |
+ return ArchInvalid, err |
|
| 156 |
+ } |
|
| 157 |
+ |
|
| 154 | 158 |
switch strings.ToLower(arch) {
|
| 155 | 159 |
case "x86": |
| 156 | 160 |
return ArchX86, nil |
| ... | ... |
@@ -185,7 +215,7 @@ func GetArchFromString(arch string) (ScmpArch, error) {
|
| 185 | 185 |
case "s390x": |
| 186 | 186 |
return ArchS390X, nil |
| 187 | 187 |
default: |
| 188 |
- return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %s", arch)
|
|
| 188 |
+ return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %q", arch)
|
|
| 189 | 189 |
} |
| 190 | 190 |
} |
| 191 | 191 |
|
| ... | ... |
@@ -229,7 +259,7 @@ func (a ScmpArch) String() string {
|
| 229 | 229 |
case ArchInvalid: |
| 230 | 230 |
return "Invalid architecture" |
| 231 | 231 |
default: |
| 232 |
- return "Unknown architecture" |
|
| 232 |
+ return fmt.Sprintf("Unknown architecture %#x", uint(a))
|
|
| 233 | 233 |
} |
| 234 | 234 |
} |
| 235 | 235 |
|
| ... | ... |
@@ -253,7 +283,7 @@ func (a ScmpCompareOp) String() string {
|
| 253 | 253 |
case CompareInvalid: |
| 254 | 254 |
return "Invalid comparison operator" |
| 255 | 255 |
default: |
| 256 |
- return "Unrecognized comparison operator" |
|
| 256 |
+ return fmt.Sprintf("Unrecognized comparison operator %#x", uint(a))
|
|
| 257 | 257 |
} |
| 258 | 258 |
} |
| 259 | 259 |
|
| ... | ... |
@@ -269,10 +299,12 @@ func (a ScmpAction) String() string {
|
| 269 | 269 |
case ActTrace: |
| 270 | 270 |
return fmt.Sprintf("Action: Notify tracing processes with code %d",
|
| 271 | 271 |
(a >> 16)) |
| 272 |
+ case ActLog: |
|
| 273 |
+ return "Action: Log system call" |
|
| 272 | 274 |
case ActAllow: |
| 273 | 275 |
return "Action: Allow system call" |
| 274 | 276 |
default: |
| 275 |
- return "Unrecognized Action" |
|
| 277 |
+ return fmt.Sprintf("Unrecognized Action %#x", uint(a))
|
|
| 276 | 278 |
} |
| 277 | 279 |
} |
| 278 | 280 |
|
| ... | ... |
@@ -298,10 +330,29 @@ func (a ScmpAction) GetReturnCode() int16 {
|
| 298 | 298 |
// GetLibraryVersion returns the version of the library the bindings are built |
| 299 | 299 |
// against. |
| 300 | 300 |
// The version is formatted as follows: Major.Minor.Micro |
| 301 |
-func GetLibraryVersion() (major, minor, micro int) {
|
|
| 301 |
+func GetLibraryVersion() (major, minor, micro uint) {
|
|
| 302 | 302 |
return verMajor, verMinor, verMicro |
| 303 | 303 |
} |
| 304 | 304 |
|
| 305 |
+// GetApi returns the API level supported by the system. |
|
| 306 |
+// Returns a positive int containing the API level, or 0 with an error if the |
|
| 307 |
+// API level could not be detected due to the library being older than v2.4.0. |
|
| 308 |
+// See the seccomp_api_get(3) man page for details on available API levels: |
|
| 309 |
+// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3 |
|
| 310 |
+func GetApi() (uint, error) {
|
|
| 311 |
+ return getApi() |
|
| 312 |
+} |
|
| 313 |
+ |
|
| 314 |
+// SetApi forcibly sets the API level. General use of this function is strongly |
|
| 315 |
+// discouraged. |
|
| 316 |
+// Returns an error if the API level could not be set. An error is always |
|
| 317 |
+// returned if the library is older than v2.4.0 |
|
| 318 |
+// See the seccomp_api_get(3) man page for details on available API levels: |
|
| 319 |
+// https://github.com/seccomp/libseccomp/blob/master/doc/man/man3/seccomp_api_get.3 |
|
| 320 |
+func SetApi(api uint) error {
|
|
| 321 |
+ return setApi(api) |
|
| 322 |
+} |
|
| 323 |
+ |
|
| 305 | 324 |
// Syscall functions |
| 306 | 325 |
|
| 307 | 326 |
// GetName retrieves the name of a syscall from its number. |
| ... | ... |
@@ -324,7 +375,7 @@ func (s ScmpSyscall) GetNameByArch(arch ScmpArch) (string, error) {
|
| 324 | 324 |
|
| 325 | 325 |
cString := C.seccomp_syscall_resolve_num_arch(arch.toNative(), C.int(s)) |
| 326 | 326 |
if cString == nil {
|
| 327 |
- return "", fmt.Errorf("could not resolve syscall name")
|
|
| 327 |
+ return "", fmt.Errorf("could not resolve syscall name for %#x", int32(s))
|
|
| 328 | 328 |
} |
| 329 | 329 |
defer C.free(unsafe.Pointer(cString)) |
| 330 | 330 |
|
| ... | ... |
@@ -338,12 +389,16 @@ func (s ScmpSyscall) GetNameByArch(arch ScmpArch) (string, error) {
|
| 338 | 338 |
// Returns the number of the syscall, or an error if no syscall with that name |
| 339 | 339 |
// was found. |
| 340 | 340 |
func GetSyscallFromName(name string) (ScmpSyscall, error) {
|
| 341 |
+ if err := ensureSupportedVersion(); err != nil {
|
|
| 342 |
+ return 0, err |
|
| 343 |
+ } |
|
| 344 |
+ |
|
| 341 | 345 |
cString := C.CString(name) |
| 342 | 346 |
defer C.free(unsafe.Pointer(cString)) |
| 343 | 347 |
|
| 344 | 348 |
result := C.seccomp_syscall_resolve_name(cString) |
| 345 | 349 |
if result == scmpError {
|
| 346 |
- return 0, fmt.Errorf("could not resolve name to syscall")
|
|
| 350 |
+ return 0, fmt.Errorf("could not resolve name to syscall: %q", name)
|
|
| 347 | 351 |
} |
| 348 | 352 |
|
| 349 | 353 |
return ScmpSyscall(result), nil |
| ... | ... |
@@ -355,6 +410,9 @@ func GetSyscallFromName(name string) (ScmpSyscall, error) {
|
| 355 | 355 |
// Returns the number of the syscall, or an error if an invalid architecture is |
| 356 | 356 |
// passed or a syscall with that name was not found. |
| 357 | 357 |
func GetSyscallFromNameByArch(name string, arch ScmpArch) (ScmpSyscall, error) {
|
| 358 |
+ if err := ensureSupportedVersion(); err != nil {
|
|
| 359 |
+ return 0, err |
|
| 360 |
+ } |
|
| 358 | 361 |
if err := sanitizeArch(arch); err != nil {
|
| 359 | 362 |
return 0, err |
| 360 | 363 |
} |
| ... | ... |
@@ -364,7 +422,7 @@ func GetSyscallFromNameByArch(name string, arch ScmpArch) (ScmpSyscall, error) {
|
| 364 | 364 |
|
| 365 | 365 |
result := C.seccomp_syscall_resolve_name_arch(arch.toNative(), cString) |
| 366 | 366 |
if result == scmpError {
|
| 367 |
- return 0, fmt.Errorf("could not resolve name to syscall")
|
|
| 367 |
+ return 0, fmt.Errorf("could not resolve name to syscall: %q on %v", name, arch)
|
|
| 368 | 368 |
} |
| 369 | 369 |
|
| 370 | 370 |
return ScmpSyscall(result), nil |
| ... | ... |
@@ -386,12 +444,16 @@ func GetSyscallFromNameByArch(name string, arch ScmpArch) (ScmpSyscall, error) {
|
| 386 | 386 |
func MakeCondition(arg uint, comparison ScmpCompareOp, values ...uint64) (ScmpCondition, error) {
|
| 387 | 387 |
var condStruct ScmpCondition |
| 388 | 388 |
|
| 389 |
+ if err := ensureSupportedVersion(); err != nil {
|
|
| 390 |
+ return condStruct, err |
|
| 391 |
+ } |
|
| 392 |
+ |
|
| 389 | 393 |
if comparison == CompareInvalid {
|
| 390 | 394 |
return condStruct, fmt.Errorf("invalid comparison operator")
|
| 391 | 395 |
} else if arg > 5 {
|
| 392 |
- return condStruct, fmt.Errorf("syscalls only have up to 6 arguments")
|
|
| 396 |
+ return condStruct, fmt.Errorf("syscalls only have up to 6 arguments (%d given)", arg)
|
|
| 393 | 397 |
} else if len(values) > 2 {
|
| 394 |
- return condStruct, fmt.Errorf("conditions can have at most 2 arguments")
|
|
| 398 |
+ return condStruct, fmt.Errorf("conditions can have at most 2 arguments (%d given)", len(values))
|
|
| 395 | 399 |
} else if len(values) == 0 {
|
| 396 | 400 |
return condStruct, fmt.Errorf("must provide at least one value to compare against")
|
| 397 | 401 |
} |
| ... | ... |
@@ -413,6 +475,10 @@ func MakeCondition(arg uint, comparison ScmpCompareOp, values ...uint64) (ScmpCo |
| 413 | 413 |
// GetNativeArch returns architecture token representing the native kernel |
| 414 | 414 |
// architecture |
| 415 | 415 |
func GetNativeArch() (ScmpArch, error) {
|
| 416 |
+ if err := ensureSupportedVersion(); err != nil {
|
|
| 417 |
+ return ArchInvalid, err |
|
| 418 |
+ } |
|
| 419 |
+ |
|
| 416 | 420 |
arch := C.seccomp_arch_native() |
| 417 | 421 |
|
| 418 | 422 |
return archFromNative(arch) |
| ... | ... |
@@ -435,6 +501,10 @@ type ScmpFilter struct {
|
| 435 | 435 |
// Returns a reference to a valid filter context, or nil and an error if the |
| 436 | 436 |
// filter context could not be created or an invalid default action was given. |
| 437 | 437 |
func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) {
|
| 438 |
+ if err := ensureSupportedVersion(); err != nil {
|
|
| 439 |
+ return nil, err |
|
| 440 |
+ } |
|
| 441 |
+ |
|
| 438 | 442 |
if err := sanitizeAction(defaultAction); err != nil {
|
| 439 | 443 |
return nil, err |
| 440 | 444 |
} |
| ... | ... |
@@ -449,6 +519,13 @@ func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) {
|
| 449 | 449 |
filter.valid = true |
| 450 | 450 |
runtime.SetFinalizer(filter, filterFinalizer) |
| 451 | 451 |
|
| 452 |
+ // Enable TSync so all goroutines will receive the same rules |
|
| 453 |
+ // If the kernel does not support TSYNC, allow us to continue without error |
|
| 454 |
+ if err := filter.setFilterAttr(filterAttrTsync, 0x1); err != nil && err != syscall.ENOTSUP {
|
|
| 455 |
+ filter.Release() |
|
| 456 |
+ return nil, fmt.Errorf("could not create filter - error setting tsync bit: %v", err)
|
|
| 457 |
+ } |
|
| 458 |
+ |
|
| 452 | 459 |
return filter, nil |
| 453 | 460 |
} |
| 454 | 461 |
|
| ... | ... |
@@ -505,7 +582,7 @@ func (f *ScmpFilter) Release() {
|
| 505 | 505 |
// The source filter src will be released as part of the process, and will no |
| 506 | 506 |
// longer be usable or valid after this call. |
| 507 | 507 |
// To be merged, filters must NOT share any architectures, and all their |
| 508 |
-// attributes (Default Action, Bad Arch Action, No New Privs and TSync bools) |
|
| 508 |
+// attributes (Default Action, Bad Arch Action, and No New Privs bools) |
|
| 509 | 509 |
// must match. |
| 510 | 510 |
// The filter src will be merged into the filter this is called on. |
| 511 | 511 |
// The architectures of the src filter not present in the destination, and all |
| ... | ... |
@@ -678,24 +755,24 @@ func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) {
|
| 678 | 678 |
return true, nil |
| 679 | 679 |
} |
| 680 | 680 |
|
| 681 |
-// GetTsyncBit returns whether Thread Synchronization will be enabled on the |
|
| 682 |
-// filter being loaded, or an error if an issue was encountered retrieving the |
|
| 683 |
-// value. |
|
| 684 |
-// Thread Sync ensures that all members of the thread group of the calling |
|
| 685 |
-// process will share the same Seccomp filter set. |
|
| 686 |
-// Tsync is a fairly recent addition to the Linux kernel and older kernels |
|
| 687 |
-// lack support. If the running kernel does not support Tsync and it is |
|
| 688 |
-// requested in a filter, Libseccomp will not enable TSync support and will |
|
| 689 |
-// proceed as normal. |
|
| 690 |
-// This function is unavailable before v2.2 of libseccomp and will return an |
|
| 691 |
-// error. |
|
| 692 |
-func (f *ScmpFilter) GetTsyncBit() (bool, error) {
|
|
| 693 |
- tSync, err := f.getFilterAttr(filterAttrTsync) |
|
| 681 |
+// GetLogBit returns the current state the Log bit will be set to on the filter |
|
| 682 |
+// being loaded, or an error if an issue was encountered retrieving the value. |
|
| 683 |
+// The Log bit tells the kernel that all actions taken by the filter, with the |
|
| 684 |
+// exception of ActAllow, should be logged. |
|
| 685 |
+// The Log bit is only usable when libseccomp API level 3 or higher is |
|
| 686 |
+// supported. |
|
| 687 |
+func (f *ScmpFilter) GetLogBit() (bool, error) {
|
|
| 688 |
+ log, err := f.getFilterAttr(filterAttrLog) |
|
| 694 | 689 |
if err != nil {
|
| 690 |
+ api, apiErr := getApi() |
|
| 691 |
+ if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
|
|
| 692 |
+ return false, fmt.Errorf("getting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
|
|
| 693 |
+ } |
|
| 694 |
+ |
|
| 695 | 695 |
return false, err |
| 696 | 696 |
} |
| 697 | 697 |
|
| 698 |
- if tSync == 0 {
|
|
| 698 |
+ if log == 0 {
|
|
| 699 | 699 |
return false, nil |
| 700 | 700 |
} |
| 701 | 701 |
|
| ... | ... |
@@ -728,25 +805,26 @@ func (f *ScmpFilter) SetNoNewPrivsBit(state bool) error {
|
| 728 | 728 |
return f.setFilterAttr(filterAttrNNP, toSet) |
| 729 | 729 |
} |
| 730 | 730 |
|
| 731 |
-// SetTsync sets whether Thread Synchronization will be enabled on the filter |
|
| 732 |
-// being loaded. Returns an error if setting Tsync failed, or the filter is |
|
| 733 |
-// invalid. |
|
| 734 |
-// Thread Sync ensures that all members of the thread group of the calling |
|
| 735 |
-// process will share the same Seccomp filter set. |
|
| 736 |
-// Tsync is a fairly recent addition to the Linux kernel and older kernels |
|
| 737 |
-// lack support. If the running kernel does not support Tsync and it is |
|
| 738 |
-// requested in a filter, Libseccomp will not enable TSync support and will |
|
| 739 |
-// proceed as normal. |
|
| 740 |
-// This function is unavailable before v2.2 of libseccomp and will return an |
|
| 741 |
-// error. |
|
| 742 |
-func (f *ScmpFilter) SetTsync(enable bool) error {
|
|
| 731 |
+// SetLogBit sets the state of the Log bit, which will be applied on filter |
|
| 732 |
+// load, or an error if an issue was encountered setting the value. |
|
| 733 |
+// The Log bit is only usable when libseccomp API level 3 or higher is |
|
| 734 |
+// supported. |
|
| 735 |
+func (f *ScmpFilter) SetLogBit(state bool) error {
|
|
| 743 | 736 |
var toSet C.uint32_t = 0x0 |
| 744 | 737 |
|
| 745 |
- if enable {
|
|
| 738 |
+ if state {
|
|
| 746 | 739 |
toSet = 0x1 |
| 747 | 740 |
} |
| 748 | 741 |
|
| 749 |
- return f.setFilterAttr(filterAttrTsync, toSet) |
|
| 742 |
+ err := f.setFilterAttr(filterAttrLog, toSet) |
|
| 743 |
+ if err != nil {
|
|
| 744 |
+ api, apiErr := getApi() |
|
| 745 |
+ if (apiErr != nil && api == 0) || (apiErr == nil && api < 3) {
|
|
| 746 |
+ return fmt.Errorf("setting the log bit is only supported in libseccomp 2.4.0 and newer with API level 3 or higher")
|
|
| 747 |
+ } |
|
| 748 |
+ } |
|
| 749 |
+ |
|
| 750 |
+ return err |
|
| 750 | 751 |
} |
| 751 | 752 |
|
| 752 | 753 |
// SetSyscallPriority sets a syscall's priority. |
| ... | ... |
@@ -7,7 +7,6 @@ package seccomp |
| 7 | 7 |
|
| 8 | 8 |
import ( |
| 9 | 9 |
"fmt" |
| 10 |
- "os" |
|
| 11 | 10 |
"syscall" |
| 12 | 11 |
) |
| 13 | 12 |
|
| ... | ... |
@@ -17,47 +16,20 @@ import ( |
| 17 | 17 |
|
| 18 | 18 |
// #cgo pkg-config: libseccomp |
| 19 | 19 |
/* |
| 20 |
+#include <errno.h> |
|
| 20 | 21 |
#include <stdlib.h> |
| 21 | 22 |
#include <seccomp.h> |
| 22 | 23 |
|
| 23 | 24 |
#if SCMP_VER_MAJOR < 2 |
| 24 |
-#error Minimum supported version of Libseccomp is v2.1.0 |
|
| 25 |
-#elif SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 1 |
|
| 26 |
-#error Minimum supported version of Libseccomp is v2.1.0 |
|
| 25 |
+#error Minimum supported version of Libseccomp is v2.2.0 |
|
| 26 |
+#elif SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 2 |
|
| 27 |
+#error Minimum supported version of Libseccomp is v2.2.0 |
|
| 27 | 28 |
#endif |
| 28 | 29 |
|
| 29 | 30 |
#define ARCH_BAD ~0 |
| 30 | 31 |
|
| 31 | 32 |
const uint32_t C_ARCH_BAD = ARCH_BAD; |
| 32 | 33 |
|
| 33 |
-#ifndef SCMP_ARCH_AARCH64 |
|
| 34 |
-#define SCMP_ARCH_AARCH64 ARCH_BAD |
|
| 35 |
-#endif |
|
| 36 |
- |
|
| 37 |
-#ifndef SCMP_ARCH_MIPS |
|
| 38 |
-#define SCMP_ARCH_MIPS ARCH_BAD |
|
| 39 |
-#endif |
|
| 40 |
- |
|
| 41 |
-#ifndef SCMP_ARCH_MIPS64 |
|
| 42 |
-#define SCMP_ARCH_MIPS64 ARCH_BAD |
|
| 43 |
-#endif |
|
| 44 |
- |
|
| 45 |
-#ifndef SCMP_ARCH_MIPS64N32 |
|
| 46 |
-#define SCMP_ARCH_MIPS64N32 ARCH_BAD |
|
| 47 |
-#endif |
|
| 48 |
- |
|
| 49 |
-#ifndef SCMP_ARCH_MIPSEL |
|
| 50 |
-#define SCMP_ARCH_MIPSEL ARCH_BAD |
|
| 51 |
-#endif |
|
| 52 |
- |
|
| 53 |
-#ifndef SCMP_ARCH_MIPSEL64 |
|
| 54 |
-#define SCMP_ARCH_MIPSEL64 ARCH_BAD |
|
| 55 |
-#endif |
|
| 56 |
- |
|
| 57 |
-#ifndef SCMP_ARCH_MIPSEL64N32 |
|
| 58 |
-#define SCMP_ARCH_MIPSEL64N32 ARCH_BAD |
|
| 59 |
-#endif |
|
| 60 |
- |
|
| 61 | 34 |
#ifndef SCMP_ARCH_PPC |
| 62 | 35 |
#define SCMP_ARCH_PPC ARCH_BAD |
| 63 | 36 |
#endif |
| ... | ... |
@@ -96,22 +68,29 @@ const uint32_t C_ARCH_PPC64LE = SCMP_ARCH_PPC64LE; |
| 96 | 96 |
const uint32_t C_ARCH_S390 = SCMP_ARCH_S390; |
| 97 | 97 |
const uint32_t C_ARCH_S390X = SCMP_ARCH_S390X; |
| 98 | 98 |
|
| 99 |
+#ifndef SCMP_ACT_LOG |
|
| 100 |
+#define SCMP_ACT_LOG 0x7ffc0000U |
|
| 101 |
+#endif |
|
| 102 |
+ |
|
| 99 | 103 |
const uint32_t C_ACT_KILL = SCMP_ACT_KILL; |
| 100 | 104 |
const uint32_t C_ACT_TRAP = SCMP_ACT_TRAP; |
| 101 | 105 |
const uint32_t C_ACT_ERRNO = SCMP_ACT_ERRNO(0); |
| 102 | 106 |
const uint32_t C_ACT_TRACE = SCMP_ACT_TRACE(0); |
| 107 |
+const uint32_t C_ACT_LOG = SCMP_ACT_LOG; |
|
| 103 | 108 |
const uint32_t C_ACT_ALLOW = SCMP_ACT_ALLOW; |
| 104 | 109 |
|
| 105 |
-// If TSync is not supported, make sure it doesn't map to a supported filter attribute |
|
| 106 |
-// Don't worry about major version < 2, the minimum version checks should catch that case |
|
| 107 |
-#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 2 |
|
| 108 |
-#define SCMP_FLTATR_CTL_TSYNC _SCMP_CMP_MIN |
|
| 110 |
+// The libseccomp SCMP_FLTATR_CTL_LOG member of the scmp_filter_attr enum was |
|
| 111 |
+// added in v2.4.0 |
|
| 112 |
+#if (SCMP_VER_MAJOR < 2) || \ |
|
| 113 |
+ (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4) |
|
| 114 |
+#define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN |
|
| 109 | 115 |
#endif |
| 110 | 116 |
|
| 111 | 117 |
const uint32_t C_ATTRIBUTE_DEFAULT = (uint32_t)SCMP_FLTATR_ACT_DEFAULT; |
| 112 | 118 |
const uint32_t C_ATTRIBUTE_BADARCH = (uint32_t)SCMP_FLTATR_ACT_BADARCH; |
| 113 | 119 |
const uint32_t C_ATTRIBUTE_NNP = (uint32_t)SCMP_FLTATR_CTL_NNP; |
| 114 | 120 |
const uint32_t C_ATTRIBUTE_TSYNC = (uint32_t)SCMP_FLTATR_CTL_TSYNC; |
| 121 |
+const uint32_t C_ATTRIBUTE_LOG = (uint32_t)SCMP_FLTATR_CTL_LOG; |
|
| 115 | 122 |
|
| 116 | 123 |
const int C_CMP_NE = (int)SCMP_CMP_NE; |
| 117 | 124 |
const int C_CMP_LT = (int)SCMP_CMP_LT; |
| ... | ... |
@@ -125,25 +104,80 @@ const int C_VERSION_MAJOR = SCMP_VER_MAJOR; |
| 125 | 125 |
const int C_VERSION_MINOR = SCMP_VER_MINOR; |
| 126 | 126 |
const int C_VERSION_MICRO = SCMP_VER_MICRO; |
| 127 | 127 |
|
| 128 |
+#if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 3 |
|
| 129 |
+unsigned int get_major_version() |
|
| 130 |
+{
|
|
| 131 |
+ return seccomp_version()->major; |
|
| 132 |
+} |
|
| 133 |
+ |
|
| 134 |
+unsigned int get_minor_version() |
|
| 135 |
+{
|
|
| 136 |
+ return seccomp_version()->minor; |
|
| 137 |
+} |
|
| 138 |
+ |
|
| 139 |
+unsigned int get_micro_version() |
|
| 140 |
+{
|
|
| 141 |
+ return seccomp_version()->micro; |
|
| 142 |
+} |
|
| 143 |
+#else |
|
| 144 |
+unsigned int get_major_version() |
|
| 145 |
+{
|
|
| 146 |
+ return (unsigned int)C_VERSION_MAJOR; |
|
| 147 |
+} |
|
| 148 |
+ |
|
| 149 |
+unsigned int get_minor_version() |
|
| 150 |
+{
|
|
| 151 |
+ return (unsigned int)C_VERSION_MINOR; |
|
| 152 |
+} |
|
| 153 |
+ |
|
| 154 |
+unsigned int get_micro_version() |
|
| 155 |
+{
|
|
| 156 |
+ return (unsigned int)C_VERSION_MICRO; |
|
| 157 |
+} |
|
| 158 |
+#endif |
|
| 159 |
+ |
|
| 160 |
+// The libseccomp API level functions were added in v2.4.0 |
|
| 161 |
+#if (SCMP_VER_MAJOR < 2) || \ |
|
| 162 |
+ (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4) |
|
| 163 |
+const unsigned int seccomp_api_get(void) |
|
| 164 |
+{
|
|
| 165 |
+ // libseccomp-golang requires libseccomp v2.2.0, at a minimum, which |
|
| 166 |
+ // supported API level 2. However, the kernel may not support API level |
|
| 167 |
+ // 2 constructs which are the seccomp() system call and the TSYNC |
|
| 168 |
+ // filter flag. Return the "reserved" value of 0 here to indicate that |
|
| 169 |
+ // proper API level support is not available in libseccomp. |
|
| 170 |
+ return 0; |
|
| 171 |
+} |
|
| 172 |
+ |
|
| 173 |
+int seccomp_api_set(unsigned int level) |
|
| 174 |
+{
|
|
| 175 |
+ return -EOPNOTSUPP; |
|
| 176 |
+} |
|
| 177 |
+#endif |
|
| 178 |
+ |
|
| 128 | 179 |
typedef struct scmp_arg_cmp* scmp_cast_t; |
| 129 | 180 |
|
| 130 |
-// Wrapper to create an scmp_arg_cmp struct |
|
| 131 |
-void* |
|
| 132 |
-make_struct_arg_cmp( |
|
| 133 |
- unsigned int arg, |
|
| 134 |
- int compare, |
|
| 135 |
- uint64_t a, |
|
| 136 |
- uint64_t b |
|
| 137 |
- ) |
|
| 181 |
+void* make_arg_cmp_array(unsigned int length) |
|
| 138 | 182 |
{
|
| 139 |
- struct scmp_arg_cmp *s = malloc(sizeof(struct scmp_arg_cmp)); |
|
| 183 |
+ return calloc(length, sizeof(struct scmp_arg_cmp)); |
|
| 184 |
+} |
|
| 140 | 185 |
|
| 141 |
- s->arg = arg; |
|
| 142 |
- s->op = compare; |
|
| 143 |
- s->datum_a = a; |
|
| 144 |
- s->datum_b = b; |
|
| 186 |
+// Wrapper to add an scmp_arg_cmp struct to an existing arg_cmp array |
|
| 187 |
+void add_struct_arg_cmp( |
|
| 188 |
+ struct scmp_arg_cmp* arr, |
|
| 189 |
+ unsigned int pos, |
|
| 190 |
+ unsigned int arg, |
|
| 191 |
+ int compare, |
|
| 192 |
+ uint64_t a, |
|
| 193 |
+ uint64_t b |
|
| 194 |
+ ) |
|
| 195 |
+{
|
|
| 196 |
+ arr[pos].arg = arg; |
|
| 197 |
+ arr[pos].op = compare; |
|
| 198 |
+ arr[pos].datum_a = a; |
|
| 199 |
+ arr[pos].datum_b = b; |
|
| 145 | 200 |
|
| 146 |
- return s; |
|
| 201 |
+ return; |
|
| 147 | 202 |
} |
| 148 | 203 |
*/ |
| 149 | 204 |
import "C" |
| ... | ... |
@@ -158,6 +192,7 @@ const ( |
| 158 | 158 |
filterAttrActBadArch scmpFilterAttr = iota |
| 159 | 159 |
filterAttrNNP scmpFilterAttr = iota |
| 160 | 160 |
filterAttrTsync scmpFilterAttr = iota |
| 161 |
+ filterAttrLog scmpFilterAttr = iota |
|
| 161 | 162 |
) |
| 162 | 163 |
|
| 163 | 164 |
const ( |
| ... | ... |
@@ -168,7 +203,7 @@ const ( |
| 168 | 168 |
archEnd ScmpArch = ArchS390X |
| 169 | 169 |
// Comparison boundaries to check for action validity |
| 170 | 170 |
actionStart ScmpAction = ActKill |
| 171 |
- actionEnd ScmpAction = ActAllow |
|
| 171 |
+ actionEnd ScmpAction = ActLog |
|
| 172 | 172 |
// Comparison boundaries to check for comparison operator validity |
| 173 | 173 |
compareOpStart ScmpCompareOp = CompareNotEqual |
| 174 | 174 |
compareOpEnd ScmpCompareOp = CompareMaskedEqual |
| ... | ... |
@@ -178,26 +213,49 @@ var ( |
| 178 | 178 |
// Error thrown on bad filter context |
| 179 | 179 |
errBadFilter = fmt.Errorf("filter is invalid or uninitialized")
|
| 180 | 180 |
// Constants representing library major, minor, and micro versions |
| 181 |
- verMajor = int(C.C_VERSION_MAJOR) |
|
| 182 |
- verMinor = int(C.C_VERSION_MINOR) |
|
| 183 |
- verMicro = int(C.C_VERSION_MICRO) |
|
| 181 |
+ verMajor = uint(C.get_major_version()) |
|
| 182 |
+ verMinor = uint(C.get_minor_version()) |
|
| 183 |
+ verMicro = uint(C.get_micro_version()) |
|
| 184 | 184 |
) |
| 185 | 185 |
|
| 186 | 186 |
// Nonexported functions |
| 187 | 187 |
|
| 188 | 188 |
// Check if library version is greater than or equal to the given one |
| 189 |
-func checkVersionAbove(major, minor, micro int) bool {
|
|
| 189 |
+func checkVersionAbove(major, minor, micro uint) bool {
|
|
| 190 | 190 |
return (verMajor > major) || |
| 191 | 191 |
(verMajor == major && verMinor > minor) || |
| 192 | 192 |
(verMajor == major && verMinor == minor && verMicro >= micro) |
| 193 | 193 |
} |
| 194 | 194 |
|
| 195 |
-// Init function: Verify library version is appropriate |
|
| 196 |
-func init() {
|
|
| 197 |
- if !checkVersionAbove(2, 1, 0) {
|
|
| 198 |
- fmt.Fprintf(os.Stderr, "Libseccomp version too low: minimum supported is 2.1.0, detected %d.%d.%d", C.C_VERSION_MAJOR, C.C_VERSION_MINOR, C.C_VERSION_MICRO) |
|
| 199 |
- os.Exit(-1) |
|
| 195 |
+// Ensure that the library is supported, i.e. >= 2.2.0. |
|
| 196 |
+func ensureSupportedVersion() error {
|
|
| 197 |
+ if !checkVersionAbove(2, 2, 0) {
|
|
| 198 |
+ return VersionError{}
|
|
| 199 |
+ } |
|
| 200 |
+ return nil |
|
| 201 |
+} |
|
| 202 |
+ |
|
| 203 |
+// Get the API level |
|
| 204 |
+func getApi() (uint, error) {
|
|
| 205 |
+ api := C.seccomp_api_get() |
|
| 206 |
+ if api == 0 {
|
|
| 207 |
+ return 0, fmt.Errorf("API level operations are not supported")
|
|
| 200 | 208 |
} |
| 209 |
+ |
|
| 210 |
+ return uint(api), nil |
|
| 211 |
+} |
|
| 212 |
+ |
|
| 213 |
+// Set the API level |
|
| 214 |
+func setApi(api uint) error {
|
|
| 215 |
+ if retCode := C.seccomp_api_set(C.uint(api)); retCode != 0 {
|
|
| 216 |
+ if syscall.Errno(-1*retCode) == syscall.EOPNOTSUPP {
|
|
| 217 |
+ return fmt.Errorf("API level operations are not supported")
|
|
| 218 |
+ } |
|
| 219 |
+ |
|
| 220 |
+ return fmt.Errorf("could not set API level: %v", retCode)
|
|
| 221 |
+ } |
|
| 222 |
+ |
|
| 223 |
+ return nil |
|
| 201 | 224 |
} |
| 202 | 225 |
|
| 203 | 226 |
// Filter helpers |
| ... | ... |
@@ -216,10 +274,6 @@ func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) {
|
| 216 | 216 |
return 0x0, errBadFilter |
| 217 | 217 |
} |
| 218 | 218 |
|
| 219 |
- if !checkVersionAbove(2, 2, 0) && attr == filterAttrTsync {
|
|
| 220 |
- return 0x0, fmt.Errorf("the thread synchronization attribute is not supported in this version of the library")
|
|
| 221 |
- } |
|
| 222 |
- |
|
| 223 | 219 |
var attribute C.uint32_t |
| 224 | 220 |
|
| 225 | 221 |
retCode := C.seccomp_attr_get(f.filterCtx, attr.toNative(), &attribute) |
| ... | ... |
@@ -239,10 +293,6 @@ func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, value C.uint32_t) error |
| 239 | 239 |
return errBadFilter |
| 240 | 240 |
} |
| 241 | 241 |
|
| 242 |
- if !checkVersionAbove(2, 2, 0) && attr == filterAttrTsync {
|
|
| 243 |
- return fmt.Errorf("the thread synchronization attribute is not supported in this version of the library")
|
|
| 244 |
- } |
|
| 245 |
- |
|
| 246 | 242 |
retCode := C.seccomp_attr_set(f.filterCtx, attr.toNative(), value) |
| 247 | 243 |
if retCode != 0 {
|
| 248 | 244 |
return syscall.Errno(-1 * retCode) |
| ... | ... |
@@ -254,12 +304,9 @@ func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, value C.uint32_t) error |
| 254 | 254 |
// DOES NOT LOCK OR CHECK VALIDITY |
| 255 | 255 |
// Assumes caller has already done this |
| 256 | 256 |
// Wrapper for seccomp_rule_add_... functions |
| 257 |
-func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact bool, cond C.scmp_cast_t) error {
|
|
| 258 |
- var length C.uint |
|
| 259 |
- if cond != nil {
|
|
| 260 |
- length = 1 |
|
| 261 |
- } else {
|
|
| 262 |
- length = 0 |
|
| 257 |
+func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact bool, length C.uint, cond C.scmp_cast_t) error {
|
|
| 258 |
+ if length != 0 && cond == nil {
|
|
| 259 |
+ return fmt.Errorf("null conditions list, but length is nonzero")
|
|
| 263 | 260 |
} |
| 264 | 261 |
|
| 265 | 262 |
var retCode C.int |
| ... | ... |
@@ -270,9 +317,11 @@ func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact b |
| 270 | 270 |
} |
| 271 | 271 |
|
| 272 | 272 |
if syscall.Errno(-1*retCode) == syscall.EFAULT {
|
| 273 |
- return fmt.Errorf("unrecognized syscall")
|
|
| 273 |
+ return fmt.Errorf("unrecognized syscall %#x", int32(call))
|
|
| 274 | 274 |
} else if syscall.Errno(-1*retCode) == syscall.EPERM {
|
| 275 | 275 |
return fmt.Errorf("requested action matches default action of filter")
|
| 276 |
+ } else if syscall.Errno(-1*retCode) == syscall.EINVAL {
|
|
| 277 |
+ return fmt.Errorf("two checks on same syscall argument")
|
|
| 276 | 278 |
} else if retCode != 0 {
|
| 277 | 279 |
return syscall.Errno(-1 * retCode) |
| 278 | 280 |
} |
| ... | ... |
@@ -290,22 +339,32 @@ func (f *ScmpFilter) addRuleGeneric(call ScmpSyscall, action ScmpAction, exact b |
| 290 | 290 |
} |
| 291 | 291 |
|
| 292 | 292 |
if len(conds) == 0 {
|
| 293 |
- if err := f.addRuleWrapper(call, action, exact, nil); err != nil {
|
|
| 293 |
+ if err := f.addRuleWrapper(call, action, exact, 0, nil); err != nil {
|
|
| 294 | 294 |
return err |
| 295 | 295 |
} |
| 296 | 296 |
} else {
|
| 297 | 297 |
// We don't support conditional filtering in library version v2.1 |
| 298 | 298 |
if !checkVersionAbove(2, 2, 1) {
|
| 299 |
- return fmt.Errorf("conditional filtering requires libseccomp version >= 2.2.1")
|
|
| 299 |
+ return VersionError{
|
|
| 300 |
+ message: "conditional filtering is not supported", |
|
| 301 |
+ minimum: "2.2.1", |
|
| 302 |
+ } |
|
| 303 |
+ } |
|
| 304 |
+ |
|
| 305 |
+ argsArr := C.make_arg_cmp_array(C.uint(len(conds))) |
|
| 306 |
+ if argsArr == nil {
|
|
| 307 |
+ return fmt.Errorf("error allocating memory for conditions")
|
|
| 300 | 308 |
} |
| 309 |
+ defer C.free(argsArr) |
|
| 301 | 310 |
|
| 302 |
- for _, cond := range conds {
|
|
| 303 |
- cmpStruct := C.make_struct_arg_cmp(C.uint(cond.Argument), cond.Op.toNative(), C.uint64_t(cond.Operand1), C.uint64_t(cond.Operand2)) |
|
| 304 |
- defer C.free(cmpStruct) |
|
| 311 |
+ for i, cond := range conds {
|
|
| 312 |
+ C.add_struct_arg_cmp(C.scmp_cast_t(argsArr), C.uint(i), |
|
| 313 |
+ C.uint(cond.Argument), cond.Op.toNative(), |
|
| 314 |
+ C.uint64_t(cond.Operand1), C.uint64_t(cond.Operand2)) |
|
| 315 |
+ } |
|
| 305 | 316 |
|
| 306 |
- if err := f.addRuleWrapper(call, action, exact, C.scmp_cast_t(cmpStruct)); err != nil {
|
|
| 307 |
- return err |
|
| 308 |
- } |
|
| 317 |
+ if err := f.addRuleWrapper(call, action, exact, C.uint(len(conds)), C.scmp_cast_t(argsArr)); err != nil {
|
|
| 318 |
+ return err |
|
| 309 | 319 |
} |
| 310 | 320 |
} |
| 311 | 321 |
|
| ... | ... |
@@ -317,11 +376,11 @@ func (f *ScmpFilter) addRuleGeneric(call ScmpSyscall, action ScmpAction, exact b |
| 317 | 317 |
// Helper - Sanitize Arch token input |
| 318 | 318 |
func sanitizeArch(in ScmpArch) error {
|
| 319 | 319 |
if in < archStart || in > archEnd {
|
| 320 |
- return fmt.Errorf("unrecognized architecture")
|
|
| 320 |
+ return fmt.Errorf("unrecognized architecture %#x", uint(in))
|
|
| 321 | 321 |
} |
| 322 | 322 |
|
| 323 | 323 |
if in.toNative() == C.C_ARCH_BAD {
|
| 324 |
- return fmt.Errorf("architecture is not supported on this version of the library")
|
|
| 324 |
+ return fmt.Errorf("architecture %v is not supported on this version of the library", in)
|
|
| 325 | 325 |
} |
| 326 | 326 |
|
| 327 | 327 |
return nil |
| ... | ... |
@@ -330,7 +389,7 @@ func sanitizeArch(in ScmpArch) error {
|
| 330 | 330 |
func sanitizeAction(in ScmpAction) error {
|
| 331 | 331 |
inTmp := in & 0x0000FFFF |
| 332 | 332 |
if inTmp < actionStart || inTmp > actionEnd {
|
| 333 |
- return fmt.Errorf("unrecognized action")
|
|
| 333 |
+ return fmt.Errorf("unrecognized action %#x", uint(inTmp))
|
|
| 334 | 334 |
} |
| 335 | 335 |
|
| 336 | 336 |
if inTmp != ActTrace && inTmp != ActErrno && (in&0xFFFF0000) != 0 {
|
| ... | ... |
@@ -342,7 +401,7 @@ func sanitizeAction(in ScmpAction) error {
|
| 342 | 342 |
|
| 343 | 343 |
func sanitizeCompareOp(in ScmpCompareOp) error {
|
| 344 | 344 |
if in < compareOpStart || in > compareOpEnd {
|
| 345 |
- return fmt.Errorf("unrecognized comparison operator")
|
|
| 345 |
+ return fmt.Errorf("unrecognized comparison operator %#x", uint(in))
|
|
| 346 | 346 |
} |
| 347 | 347 |
|
| 348 | 348 |
return nil |
| ... | ... |
@@ -385,7 +444,7 @@ func archFromNative(a C.uint32_t) (ScmpArch, error) {
|
| 385 | 385 |
case C.C_ARCH_S390X: |
| 386 | 386 |
return ArchS390X, nil |
| 387 | 387 |
default: |
| 388 |
- return 0x0, fmt.Errorf("unrecognized architecture")
|
|
| 388 |
+ return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a))
|
|
| 389 | 389 |
} |
| 390 | 390 |
} |
| 391 | 391 |
|
| ... | ... |
@@ -464,10 +523,12 @@ func actionFromNative(a C.uint32_t) (ScmpAction, error) {
|
| 464 | 464 |
return ActErrno.SetReturnCode(int16(aTmp)), nil |
| 465 | 465 |
case C.C_ACT_TRACE: |
| 466 | 466 |
return ActTrace.SetReturnCode(int16(aTmp)), nil |
| 467 |
+ case C.C_ACT_LOG: |
|
| 468 |
+ return ActLog, nil |
|
| 467 | 469 |
case C.C_ACT_ALLOW: |
| 468 | 470 |
return ActAllow, nil |
| 469 | 471 |
default: |
| 470 |
- return 0x0, fmt.Errorf("unrecognized action")
|
|
| 472 |
+ return 0x0, fmt.Errorf("unrecognized action %#x", uint32(a))
|
|
| 471 | 473 |
} |
| 472 | 474 |
} |
| 473 | 475 |
|
| ... | ... |
@@ -482,6 +543,8 @@ func (a ScmpAction) toNative() C.uint32_t {
|
| 482 | 482 |
return C.C_ACT_ERRNO | (C.uint32_t(a) >> 16) |
| 483 | 483 |
case ActTrace: |
| 484 | 484 |
return C.C_ACT_TRACE | (C.uint32_t(a) >> 16) |
| 485 |
+ case ActLog: |
|
| 486 |
+ return C.C_ACT_LOG |
|
| 485 | 487 |
case ActAllow: |
| 486 | 488 |
return C.C_ACT_ALLOW |
| 487 | 489 |
default: |
| ... | ... |
@@ -500,6 +563,8 @@ func (a scmpFilterAttr) toNative() uint32 {
|
| 500 | 500 |
return uint32(C.C_ATTRIBUTE_NNP) |
| 501 | 501 |
case filterAttrTsync: |
| 502 | 502 |
return uint32(C.C_ATTRIBUTE_TSYNC) |
| 503 |
+ case filterAttrLog: |
|
| 504 |
+ return uint32(C.C_ATTRIBUTE_LOG) |
|
| 503 | 505 |
default: |
| 504 | 506 |
return 0x0 |
| 505 | 507 |
} |