1// +build linux 2 3// Public API specification for libseccomp Go bindings 4// Contains public API for the bindings 5 6// Package seccomp provides bindings for libseccomp, a library wrapping the Linux 7// seccomp syscall. Seccomp enables an application to restrict system call use 8// for itself and its children. 9package seccomp 10 11import ( 12 "fmt" 13 "os" 14 "runtime" 15 "strings" 16 "sync" 17 "syscall" 18 "unsafe" 19) 20 21// C wrapping code 22 23// #cgo pkg-config: libseccomp 24// #include <stdlib.h> 25// #include <seccomp.h> 26import "C" 27 28// Exported types 29 30// ScmpArch represents a CPU architecture. Seccomp can restrict syscalls on a 31// per-architecture basis. 32type ScmpArch uint 33 34// ScmpAction represents an action to be taken on a filter rule match in 35// libseccomp 36type ScmpAction uint 37 38// ScmpCompareOp represents a comparison operator which can be used in a filter 39// rule 40type ScmpCompareOp uint 41 42// ScmpCondition represents a rule in a libseccomp filter context 43type ScmpCondition struct { 44 Argument uint `json:"argument,omitempty"` 45 Op ScmpCompareOp `json:"operator,omitempty"` 46 Operand1 uint64 `json:"operand_one,omitempty"` 47 Operand2 uint64 `json:"operand_two,omitempty"` 48} 49 50// ScmpSyscall represents a Linux System Call 51type ScmpSyscall int32 52 53// Exported Constants 54 55const ( 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 59 60 // ArchInvalid is a placeholder to ensure uninitialized ScmpArch 61 // variables are invalid 62 ArchInvalid ScmpArch = iota 63 // ArchNative is the native architecture of the kernel 64 ArchNative ScmpArch = iota 65 // ArchX86 represents 32-bit x86 syscalls 66 ArchX86 ScmpArch = iota 67 // ArchAMD64 represents 64-bit x86-64 syscalls 68 ArchAMD64 ScmpArch = iota 69 // ArchX32 represents 64-bit x86-64 syscalls (32-bit pointers) 70 ArchX32 ScmpArch = iota 71 // ArchARM represents 32-bit ARM syscalls 72 ArchARM ScmpArch = iota 73 // ArchARM64 represents 64-bit ARM syscalls 74 ArchARM64 ScmpArch = iota 75 // ArchMIPS represents 32-bit MIPS syscalls 76 ArchMIPS ScmpArch = iota 77 // ArchMIPS64 represents 64-bit MIPS syscalls 78 ArchMIPS64 ScmpArch = iota 79 // ArchMIPS64N32 represents 64-bit MIPS syscalls (32-bit pointers) 80 ArchMIPS64N32 ScmpArch = iota 81 // ArchMIPSEL represents 32-bit MIPS syscalls (little endian) 82 ArchMIPSEL ScmpArch = iota 83 // ArchMIPSEL64 represents 64-bit MIPS syscalls (little endian) 84 ArchMIPSEL64 ScmpArch = iota 85 // ArchMIPSEL64N32 represents 64-bit MIPS syscalls (little endian, 86 // 32-bit pointers) 87 ArchMIPSEL64N32 ScmpArch = iota 88 // ArchPPC represents 32-bit POWERPC syscalls 89 ArchPPC ScmpArch = iota 90 // ArchPPC64 represents 64-bit POWER syscalls (big endian) 91 ArchPPC64 ScmpArch = iota 92 // ArchPPC64LE represents 64-bit POWER syscalls (little endian) 93 ArchPPC64LE ScmpArch = iota 94 // ArchS390 represents 31-bit System z/390 syscalls 95 ArchS390 ScmpArch = iota 96 // ArchS390X represents 64-bit System z/390 syscalls 97 ArchS390X ScmpArch = iota 98) 99 100const ( 101 // Supported actions on filter match 102 103 // ActInvalid is a placeholder to ensure uninitialized ScmpAction 104 // variables are invalid 105 ActInvalid ScmpAction = iota 106 // ActKill kills the process 107 ActKill ScmpAction = iota 108 // ActTrap throws SIGSYS 109 ActTrap ScmpAction = iota 110 // ActErrno causes the syscall to return a negative error code. This 111 // code can be set with the SetReturnCode method 112 ActErrno ScmpAction = iota 113 // ActTrace causes the syscall to notify tracing processes with the 114 // given error code. This code can be set with the SetReturnCode method 115 ActTrace ScmpAction = iota 116 // ActAllow permits the syscall to continue execution 117 ActAllow ScmpAction = iota 118) 119 120const ( 121 // These are comparison operators used in conditional seccomp rules 122 // They are used to compare the value of a single argument of a syscall 123 // against a user-defined constant 124 125 // CompareInvalid is a placeholder to ensure uninitialized ScmpCompareOp 126 // variables are invalid 127 CompareInvalid ScmpCompareOp = iota 128 // CompareNotEqual returns true if the argument is not equal to the 129 // given value 130 CompareNotEqual ScmpCompareOp = iota 131 // CompareLess returns true if the argument is less than the given value 132 CompareLess ScmpCompareOp = iota 133 // CompareLessOrEqual returns true if the argument is less than or equal 134 // to the given value 135 CompareLessOrEqual ScmpCompareOp = iota 136 // CompareEqual returns true if the argument is equal to the given value 137 CompareEqual ScmpCompareOp = iota 138 // CompareGreaterEqual returns true if the argument is greater than or 139 // equal to the given value 140 CompareGreaterEqual ScmpCompareOp = iota 141 // CompareGreater returns true if the argument is greater than the given 142 // value 143 CompareGreater ScmpCompareOp = iota 144 // CompareMaskedEqual returns true if the argument is equal to the given 145 // value, when masked (bitwise &) against the second given value 146 CompareMaskedEqual ScmpCompareOp = iota 147) 148 149// Helpers for types 150 151// GetArchFromString returns an ScmpArch constant from a string representing an 152// architecture 153func GetArchFromString(arch string) (ScmpArch, error) { 154 switch strings.ToLower(arch) { 155 case "x86": 156 return ArchX86, nil 157 case "amd64", "x86-64", "x86_64", "x64": 158 return ArchAMD64, nil 159 case "x32": 160 return ArchX32, nil 161 case "arm": 162 return ArchARM, nil 163 case "arm64", "aarch64": 164 return ArchARM64, nil 165 case "mips": 166 return ArchMIPS, nil 167 case "mips64": 168 return ArchMIPS64, nil 169 case "mips64n32": 170 return ArchMIPS64N32, nil 171 case "mipsel": 172 return ArchMIPSEL, nil 173 case "mipsel64": 174 return ArchMIPSEL64, nil 175 case "mipsel64n32": 176 return ArchMIPSEL64N32, nil 177 case "ppc": 178 return ArchPPC, nil 179 case "ppc64": 180 return ArchPPC64, nil 181 case "ppc64le": 182 return ArchPPC64LE, nil 183 case "s390": 184 return ArchS390, nil 185 case "s390x": 186 return ArchS390X, nil 187 default: 188 return ArchInvalid, fmt.Errorf("cannot convert unrecognized string %s", arch) 189 } 190} 191 192// String returns a string representation of an architecture constant 193func (a ScmpArch) String() string { 194 switch a { 195 case ArchX86: 196 return "x86" 197 case ArchAMD64: 198 return "amd64" 199 case ArchX32: 200 return "x32" 201 case ArchARM: 202 return "arm" 203 case ArchARM64: 204 return "arm64" 205 case ArchMIPS: 206 return "mips" 207 case ArchMIPS64: 208 return "mips64" 209 case ArchMIPS64N32: 210 return "mips64n32" 211 case ArchMIPSEL: 212 return "mipsel" 213 case ArchMIPSEL64: 214 return "mipsel64" 215 case ArchMIPSEL64N32: 216 return "mipsel64n32" 217 case ArchPPC: 218 return "ppc" 219 case ArchPPC64: 220 return "ppc64" 221 case ArchPPC64LE: 222 return "ppc64le" 223 case ArchS390: 224 return "s390" 225 case ArchS390X: 226 return "s390x" 227 case ArchNative: 228 return "native" 229 case ArchInvalid: 230 return "Invalid architecture" 231 default: 232 return "Unknown architecture" 233 } 234} 235 236// String returns a string representation of a comparison operator constant 237func (a ScmpCompareOp) String() string { 238 switch a { 239 case CompareNotEqual: 240 return "Not equal" 241 case CompareLess: 242 return "Less than" 243 case CompareLessOrEqual: 244 return "Less than or equal to" 245 case CompareEqual: 246 return "Equal" 247 case CompareGreaterEqual: 248 return "Greater than or equal to" 249 case CompareGreater: 250 return "Greater than" 251 case CompareMaskedEqual: 252 return "Masked equality" 253 case CompareInvalid: 254 return "Invalid comparison operator" 255 default: 256 return "Unrecognized comparison operator" 257 } 258} 259 260// String returns a string representation of a seccomp match action 261func (a ScmpAction) String() string { 262 switch a & 0xFFFF { 263 case ActKill: 264 return "Action: Kill Process" 265 case ActTrap: 266 return "Action: Send SIGSYS" 267 case ActErrno: 268 return fmt.Sprintf("Action: Return error code %d", (a >> 16)) 269 case ActTrace: 270 return fmt.Sprintf("Action: Notify tracing processes with code %d", 271 (a >> 16)) 272 case ActAllow: 273 return "Action: Allow system call" 274 default: 275 return "Unrecognized Action" 276 } 277} 278 279// SetReturnCode adds a return code to a supporting ScmpAction, clearing any 280// existing code Only valid on ActErrno and ActTrace. Takes no action otherwise. 281// Accepts 16-bit return code as argument. 282// Returns a valid ScmpAction of the original type with the new error code set. 283func (a ScmpAction) SetReturnCode(code int16) ScmpAction { 284 aTmp := a & 0x0000FFFF 285 if aTmp == ActErrno || aTmp == ActTrace { 286 return (aTmp | (ScmpAction(code)&0xFFFF)<<16) 287 } 288 return a 289} 290 291// GetReturnCode returns the return code of an ScmpAction 292func (a ScmpAction) GetReturnCode() int16 { 293 return int16(a >> 16) 294} 295 296// General utility functions 297 298// GetLibraryVersion returns the version of the library the bindings are built 299// against. 300// The version is formatted as follows: Major.Minor.Micro 301func GetLibraryVersion() (major, minor, micro int) { 302 return verMajor, verMinor, verMicro 303} 304 305// Syscall functions 306 307// GetName retrieves the name of a syscall from its number. 308// Acts on any syscall number. 309// Returns either a string containing the name of the syscall, or an error. 310func (s ScmpSyscall) GetName() (string, error) { 311 return s.GetNameByArch(ArchNative) 312} 313 314// GetNameByArch retrieves the name of a syscall from its number for a given 315// architecture. 316// Acts on any syscall number. 317// Accepts a valid architecture constant. 318// Returns either a string containing the name of the syscall, or an error. 319// if the syscall is unrecognized or an issue occurred. 320func (s ScmpSyscall) GetNameByArch(arch ScmpArch) (string, error) { 321 if err := sanitizeArch(arch); err != nil { 322 return "", err 323 } 324 325 cString := C.seccomp_syscall_resolve_num_arch(arch.toNative(), C.int(s)) 326 if cString == nil { 327 return "", fmt.Errorf("could not resolve syscall name") 328 } 329 defer C.free(unsafe.Pointer(cString)) 330 331 finalStr := C.GoString(cString) 332 return finalStr, nil 333} 334 335// GetSyscallFromName returns the number of a syscall by name on the kernel's 336// native architecture. 337// Accepts a string containing the name of a syscall. 338// Returns the number of the syscall, or an error if no syscall with that name 339// was found. 340func GetSyscallFromName(name string) (ScmpSyscall, error) { 341 cString := C.CString(name) 342 defer C.free(unsafe.Pointer(cString)) 343 344 result := C.seccomp_syscall_resolve_name(cString) 345 if result == scmpError { 346 return 0, fmt.Errorf("could not resolve name to syscall") 347 } 348 349 return ScmpSyscall(result), nil 350} 351 352// GetSyscallFromNameByArch returns the number of a syscall by name for a given 353// architecture's ABI. 354// Accepts the name of a syscall and an architecture constant. 355// Returns the number of the syscall, or an error if an invalid architecture is 356// passed or a syscall with that name was not found. 357func GetSyscallFromNameByArch(name string, arch ScmpArch) (ScmpSyscall, error) { 358 if err := sanitizeArch(arch); err != nil { 359 return 0, err 360 } 361 362 cString := C.CString(name) 363 defer C.free(unsafe.Pointer(cString)) 364 365 result := C.seccomp_syscall_resolve_name_arch(arch.toNative(), cString) 366 if result == scmpError { 367 return 0, fmt.Errorf("could not resolve name to syscall") 368 } 369 370 return ScmpSyscall(result), nil 371} 372 373// MakeCondition creates and returns a new condition to attach to a filter rule. 374// Associated rules will only match if this condition is true. 375// Accepts the number the argument we are checking, and a comparison operator 376// and value to compare to. 377// The rule will match if argument $arg (zero-indexed) of the syscall is 378// $COMPARE_OP the provided comparison value. 379// Some comparison operators accept two values. Masked equals, for example, 380// will mask $arg of the syscall with the second value provided (via bitwise 381// AND) and then compare against the first value provided. 382// For example, in the less than or equal case, if the syscall argument was 383// 0 and the value provided was 1, the condition would match, as 0 is less 384// than or equal to 1. 385// Return either an error on bad argument or a valid ScmpCondition struct. 386func MakeCondition(arg uint, comparison ScmpCompareOp, values ...uint64) (ScmpCondition, error) { 387 var condStruct ScmpCondition 388 389 if comparison == CompareInvalid { 390 return condStruct, fmt.Errorf("invalid comparison operator") 391 } else if arg > 5 { 392 return condStruct, fmt.Errorf("syscalls only have up to 6 arguments") 393 } else if len(values) > 2 { 394 return condStruct, fmt.Errorf("conditions can have at most 2 arguments") 395 } else if len(values) == 0 { 396 return condStruct, fmt.Errorf("must provide at least one value to compare against") 397 } 398 399 condStruct.Argument = arg 400 condStruct.Op = comparison 401 condStruct.Operand1 = values[0] 402 if len(values) == 2 { 403 condStruct.Operand2 = values[1] 404 } else { 405 condStruct.Operand2 = 0 // Unused 406 } 407 408 return condStruct, nil 409} 410 411// Utility Functions 412 413// GetNativeArch returns architecture token representing the native kernel 414// architecture 415func GetNativeArch() (ScmpArch, error) { 416 arch := C.seccomp_arch_native() 417 418 return archFromNative(arch) 419} 420 421// Public Filter API 422 423// ScmpFilter represents a filter context in libseccomp. 424// A filter context is initially empty. Rules can be added to it, and it can 425// then be loaded into the kernel. 426type ScmpFilter struct { 427 filterCtx C.scmp_filter_ctx 428 valid bool 429 lock sync.Mutex 430} 431 432// NewFilter creates and returns a new filter context. 433// Accepts a default action to be taken for syscalls which match no rules in 434// the filter. 435// Returns a reference to a valid filter context, or nil and an error if the 436// filter context could not be created or an invalid default action was given. 437func NewFilter(defaultAction ScmpAction) (*ScmpFilter, error) { 438 if err := sanitizeAction(defaultAction); err != nil { 439 return nil, err 440 } 441 442 fPtr := C.seccomp_init(defaultAction.toNative()) 443 if fPtr == nil { 444 return nil, fmt.Errorf("could not create filter") 445 } 446 447 filter := new(ScmpFilter) 448 filter.filterCtx = fPtr 449 filter.valid = true 450 runtime.SetFinalizer(filter, filterFinalizer) 451 452 return filter, nil 453} 454 455// IsValid determines whether a filter context is valid to use. 456// Some operations (Release and Merge) render filter contexts invalid and 457// consequently prevent further use. 458func (f *ScmpFilter) IsValid() bool { 459 f.lock.Lock() 460 defer f.lock.Unlock() 461 462 return f.valid 463} 464 465// Reset resets a filter context, removing all its existing state. 466// Accepts a new default action to be taken for syscalls which do not match. 467// Returns an error if the filter or action provided are invalid. 468func (f *ScmpFilter) Reset(defaultAction ScmpAction) error { 469 f.lock.Lock() 470 defer f.lock.Unlock() 471 472 if err := sanitizeAction(defaultAction); err != nil { 473 return err 474 } else if !f.valid { 475 return errBadFilter 476 } 477 478 retCode := C.seccomp_reset(f.filterCtx, defaultAction.toNative()) 479 if retCode != 0 { 480 return syscall.Errno(-1 * retCode) 481 } 482 483 return nil 484} 485 486// Release releases a filter context, freeing its memory. Should be called after 487// loading into the kernel, when the filter is no longer needed. 488// After calling this function, the given filter is no longer valid and cannot 489// be used. 490// Release() will be invoked automatically when a filter context is garbage 491// collected, but can also be called manually to free memory. 492func (f *ScmpFilter) Release() { 493 f.lock.Lock() 494 defer f.lock.Unlock() 495 496 if !f.valid { 497 return 498 } 499 500 f.valid = false 501 C.seccomp_release(f.filterCtx) 502} 503 504// Merge merges two filter contexts. 505// The source filter src will be released as part of the process, and will no 506// longer be usable or valid after this call. 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) 509// must match. 510// The filter src will be merged into the filter this is called on. 511// The architectures of the src filter not present in the destination, and all 512// associated rules, will be added to the destination. 513// Returns an error if merging the filters failed. 514func (f *ScmpFilter) Merge(src *ScmpFilter) error { 515 f.lock.Lock() 516 defer f.lock.Unlock() 517 518 src.lock.Lock() 519 defer src.lock.Unlock() 520 521 if !src.valid || !f.valid { 522 return fmt.Errorf("one or more of the filter contexts is invalid or uninitialized") 523 } 524 525 // Merge the filters 526 retCode := C.seccomp_merge(f.filterCtx, src.filterCtx) 527 if syscall.Errno(-1*retCode) == syscall.EINVAL { 528 return fmt.Errorf("filters could not be merged due to a mismatch in attributes or invalid filter") 529 } else if retCode != 0 { 530 return syscall.Errno(-1 * retCode) 531 } 532 533 src.valid = false 534 535 return nil 536} 537 538// IsArchPresent checks if an architecture is present in a filter. 539// If a filter contains an architecture, it uses its default action for 540// syscalls which do not match rules in it, and its rules can match syscalls 541// for that ABI. 542// If a filter does not contain an architecture, all syscalls made to that 543// kernel ABI will fail with the filter's default Bad Architecture Action 544// (by default, killing the process). 545// Accepts an architecture constant. 546// Returns true if the architecture is present in the filter, false otherwise, 547// and an error on an invalid filter context, architecture constant, or an 548// issue with the call to libseccomp. 549func (f *ScmpFilter) IsArchPresent(arch ScmpArch) (bool, error) { 550 f.lock.Lock() 551 defer f.lock.Unlock() 552 553 if err := sanitizeArch(arch); err != nil { 554 return false, err 555 } else if !f.valid { 556 return false, errBadFilter 557 } 558 559 retCode := C.seccomp_arch_exist(f.filterCtx, arch.toNative()) 560 if syscall.Errno(-1*retCode) == syscall.EEXIST { 561 // -EEXIST is "arch not present" 562 return false, nil 563 } else if retCode != 0 { 564 return false, syscall.Errno(-1 * retCode) 565 } 566 567 return true, nil 568} 569 570// AddArch adds an architecture to the filter. 571// Accepts an architecture constant. 572// Returns an error on invalid filter context or architecture token, or an 573// issue with the call to libseccomp. 574func (f *ScmpFilter) AddArch(arch ScmpArch) error { 575 f.lock.Lock() 576 defer f.lock.Unlock() 577 578 if err := sanitizeArch(arch); err != nil { 579 return err 580 } else if !f.valid { 581 return errBadFilter 582 } 583 584 // Libseccomp returns -EEXIST if the specified architecture is already 585 // present. Succeed silently in this case, as it's not fatal, and the 586 // architecture is present already. 587 retCode := C.seccomp_arch_add(f.filterCtx, arch.toNative()) 588 if retCode != 0 && syscall.Errno(-1*retCode) != syscall.EEXIST { 589 return syscall.Errno(-1 * retCode) 590 } 591 592 return nil 593} 594 595// RemoveArch removes an architecture from the filter. 596// Accepts an architecture constant. 597// Returns an error on invalid filter context or architecture token, or an 598// issue with the call to libseccomp. 599func (f *ScmpFilter) RemoveArch(arch ScmpArch) error { 600 f.lock.Lock() 601 defer f.lock.Unlock() 602 603 if err := sanitizeArch(arch); err != nil { 604 return err 605 } else if !f.valid { 606 return errBadFilter 607 } 608 609 // Similar to AddArch, -EEXIST is returned if the arch is not present 610 // Succeed silently in that case, this is not fatal and the architecture 611 // is not present in the filter after RemoveArch 612 retCode := C.seccomp_arch_remove(f.filterCtx, arch.toNative()) 613 if retCode != 0 && syscall.Errno(-1*retCode) != syscall.EEXIST { 614 return syscall.Errno(-1 * retCode) 615 } 616 617 return nil 618} 619 620// Load loads a filter context into the kernel. 621// Returns an error if the filter context is invalid or the syscall failed. 622func (f *ScmpFilter) Load() error { 623 f.lock.Lock() 624 defer f.lock.Unlock() 625 626 if !f.valid { 627 return errBadFilter 628 } 629 630 if retCode := C.seccomp_load(f.filterCtx); retCode != 0 { 631 return syscall.Errno(-1 * retCode) 632 } 633 634 return nil 635} 636 637// GetDefaultAction returns the default action taken on a syscall which does not 638// match a rule in the filter, or an error if an issue was encountered 639// retrieving the value. 640func (f *ScmpFilter) GetDefaultAction() (ScmpAction, error) { 641 action, err := f.getFilterAttr(filterAttrActDefault) 642 if err != nil { 643 return 0x0, err 644 } 645 646 return actionFromNative(action) 647} 648 649// GetBadArchAction returns the default action taken on a syscall for an 650// architecture not in the filter, or an error if an issue was encountered 651// retrieving the value. 652func (f *ScmpFilter) GetBadArchAction() (ScmpAction, error) { 653 action, err := f.getFilterAttr(filterAttrActBadArch) 654 if err != nil { 655 return 0x0, err 656 } 657 658 return actionFromNative(action) 659} 660 661// GetNoNewPrivsBit returns the current state the No New Privileges bit will be set 662// to on the filter being loaded, or an error if an issue was encountered 663// retrieving the value. 664// The No New Privileges bit tells the kernel that new processes run with exec() 665// cannot gain more privileges than the process that ran exec(). 666// For example, a process with No New Privileges set would be unable to exec 667// setuid/setgid executables. 668func (f *ScmpFilter) GetNoNewPrivsBit() (bool, error) { 669 noNewPrivs, err := f.getFilterAttr(filterAttrNNP) 670 if err != nil { 671 return false, err 672 } 673 674 if noNewPrivs == 0 { 675 return false, nil 676 } 677 678 return true, nil 679} 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. 692func (f *ScmpFilter) GetTsyncBit() (bool, error) { 693 tSync, err := f.getFilterAttr(filterAttrTsync) 694 if err != nil { 695 return false, err 696 } 697 698 if tSync == 0 { 699 return false, nil 700 } 701 702 return true, nil 703} 704 705// SetBadArchAction sets the default action taken on a syscall for an 706// architecture not in the filter, or an error if an issue was encountered 707// setting the value. 708func (f *ScmpFilter) SetBadArchAction(action ScmpAction) error { 709 if err := sanitizeAction(action); err != nil { 710 return err 711 } 712 713 return f.setFilterAttr(filterAttrActBadArch, action.toNative()) 714} 715 716// SetNoNewPrivsBit sets the state of the No New Privileges bit, which will be 717// applied on filter load, or an error if an issue was encountered setting the 718// value. 719// Filters with No New Privileges set to 0 can only be loaded if the process 720// has the CAP_SYS_ADMIN capability. 721func (f *ScmpFilter) SetNoNewPrivsBit(state bool) error { 722 var toSet C.uint32_t = 0x0 723 724 if state { 725 toSet = 0x1 726 } 727 728 return f.setFilterAttr(filterAttrNNP, toSet) 729} 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. 742func (f *ScmpFilter) SetTsync(enable bool) error { 743 var toSet C.uint32_t = 0x0 744 745 if enable { 746 toSet = 0x1 747 } 748 749 return f.setFilterAttr(filterAttrTsync, toSet) 750} 751 752// SetSyscallPriority sets a syscall's priority. 753// This provides a hint to the filter generator in libseccomp about the 754// importance of this syscall. High-priority syscalls are placed 755// first in the filter code, and incur less overhead (at the expense of 756// lower-priority syscalls). 757func (f *ScmpFilter) SetSyscallPriority(call ScmpSyscall, priority uint8) error { 758 f.lock.Lock() 759 defer f.lock.Unlock() 760 761 if !f.valid { 762 return errBadFilter 763 } 764 765 if retCode := C.seccomp_syscall_priority(f.filterCtx, C.int(call), 766 C.uint8_t(priority)); retCode != 0 { 767 return syscall.Errno(-1 * retCode) 768 } 769 770 return nil 771} 772 773// AddRule adds a single rule for an unconditional action on a syscall. 774// Accepts the number of the syscall and the action to be taken on the call 775// being made. 776// Returns an error if an issue was encountered adding the rule. 777func (f *ScmpFilter) AddRule(call ScmpSyscall, action ScmpAction) error { 778 return f.addRuleGeneric(call, action, false, nil) 779} 780 781// AddRuleExact adds a single rule for an unconditional action on a syscall. 782// Accepts the number of the syscall and the action to be taken on the call 783// being made. 784// No modifications will be made to the rule, and it will fail to add if it 785// cannot be applied to the current architecture without modification. 786// The rule will function exactly as described, but it may not function identically 787// (or be able to be applied to) all architectures. 788// Returns an error if an issue was encountered adding the rule. 789func (f *ScmpFilter) AddRuleExact(call ScmpSyscall, action ScmpAction) error { 790 return f.addRuleGeneric(call, action, true, nil) 791} 792 793// AddRuleConditional adds a single rule for a conditional action on a syscall. 794// Returns an error if an issue was encountered adding the rule. 795// All conditions must match for the rule to match. 796// There is a bug in library versions below v2.2.1 which can, in some cases, 797// cause conditions to be lost when more than one are used. Consequently, 798// AddRuleConditional is disabled on library versions lower than v2.2.1 799func (f *ScmpFilter) AddRuleConditional(call ScmpSyscall, action ScmpAction, conds []ScmpCondition) error { 800 return f.addRuleGeneric(call, action, false, conds) 801} 802 803// AddRuleConditionalExact adds a single rule for a conditional action on a 804// syscall. 805// No modifications will be made to the rule, and it will fail to add if it 806// cannot be applied to the current architecture without modification. 807// The rule will function exactly as described, but it may not function identically 808// (or be able to be applied to) all architectures. 809// Returns an error if an issue was encountered adding the rule. 810// There is a bug in library versions below v2.2.1 which can, in some cases, 811// cause conditions to be lost when more than one are used. Consequently, 812// AddRuleConditionalExact is disabled on library versions lower than v2.2.1 813func (f *ScmpFilter) AddRuleConditionalExact(call ScmpSyscall, action ScmpAction, conds []ScmpCondition) error { 814 return f.addRuleGeneric(call, action, true, conds) 815} 816 817// ExportPFC output PFC-formatted, human-readable dump of a filter context's 818// rules to a file. 819// Accepts file to write to (must be open for writing). 820// Returns an error if writing to the file fails. 821func (f *ScmpFilter) ExportPFC(file *os.File) error { 822 f.lock.Lock() 823 defer f.lock.Unlock() 824 825 fd := file.Fd() 826 827 if !f.valid { 828 return errBadFilter 829 } 830 831 if retCode := C.seccomp_export_pfc(f.filterCtx, C.int(fd)); retCode != 0 { 832 return syscall.Errno(-1 * retCode) 833 } 834 835 return nil 836} 837 838// ExportBPF outputs Berkeley Packet Filter-formatted, kernel-readable dump of a 839// filter context's rules to a file. 840// Accepts file to write to (must be open for writing). 841// Returns an error if writing to the file fails. 842func (f *ScmpFilter) ExportBPF(file *os.File) error { 843 f.lock.Lock() 844 defer f.lock.Unlock() 845 846 fd := file.Fd() 847 848 if !f.valid { 849 return errBadFilter 850 } 851 852 if retCode := C.seccomp_export_bpf(f.filterCtx, C.int(fd)); retCode != 0 { 853 return syscall.Errno(-1 * retCode) 854 } 855 856 return nil 857} 858