seccomp_internal.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. // Internal functions for libseccomp Go bindings
  2. // No exported functions
  3. package seccomp
  4. import (
  5. "errors"
  6. "fmt"
  7. "syscall"
  8. )
  9. // Unexported C wrapping code - provides the C-Golang interface
  10. // Get the seccomp header in scope
  11. // Need stdlib.h for free() on cstrings
  12. // To compile libseccomp-golang against a specific version of libseccomp:
  13. // cd ../libseccomp && mkdir -p prefix
  14. // ./configure --prefix=$PWD/prefix && make && make install
  15. // cd ../libseccomp-golang
  16. // PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make
  17. // LD_PRELOAD=$PWD/../libseccomp/prefix/lib/libseccomp.so.2.5.0 PKG_CONFIG_PATH=$PWD/../libseccomp/prefix/lib/pkgconfig/ make test
  18. // #cgo pkg-config: libseccomp
  19. /*
  20. #include <errno.h>
  21. #include <stdlib.h>
  22. #include <seccomp.h>
  23. #if (SCMP_VER_MAJOR < 2) || \
  24. (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 3) || \
  25. (SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR == 3 && SCMP_VER_MICRO < 1)
  26. #error This package requires libseccomp >= v2.3.1
  27. #endif
  28. #define ARCH_BAD ~0
  29. const uint32_t C_ARCH_BAD = ARCH_BAD;
  30. #ifndef SCMP_ARCH_PPC
  31. #define SCMP_ARCH_PPC ARCH_BAD
  32. #endif
  33. #ifndef SCMP_ARCH_PPC64
  34. #define SCMP_ARCH_PPC64 ARCH_BAD
  35. #endif
  36. #ifndef SCMP_ARCH_PPC64LE
  37. #define SCMP_ARCH_PPC64LE ARCH_BAD
  38. #endif
  39. #ifndef SCMP_ARCH_S390
  40. #define SCMP_ARCH_S390 ARCH_BAD
  41. #endif
  42. #ifndef SCMP_ARCH_S390X
  43. #define SCMP_ARCH_S390X ARCH_BAD
  44. #endif
  45. #ifndef SCMP_ARCH_PARISC
  46. #define SCMP_ARCH_PARISC ARCH_BAD
  47. #endif
  48. #ifndef SCMP_ARCH_PARISC64
  49. #define SCMP_ARCH_PARISC64 ARCH_BAD
  50. #endif
  51. #ifndef SCMP_ARCH_RISCV64
  52. #define SCMP_ARCH_RISCV64 ARCH_BAD
  53. #endif
  54. const uint32_t C_ARCH_NATIVE = SCMP_ARCH_NATIVE;
  55. const uint32_t C_ARCH_X86 = SCMP_ARCH_X86;
  56. const uint32_t C_ARCH_X86_64 = SCMP_ARCH_X86_64;
  57. const uint32_t C_ARCH_X32 = SCMP_ARCH_X32;
  58. const uint32_t C_ARCH_ARM = SCMP_ARCH_ARM;
  59. const uint32_t C_ARCH_AARCH64 = SCMP_ARCH_AARCH64;
  60. const uint32_t C_ARCH_MIPS = SCMP_ARCH_MIPS;
  61. const uint32_t C_ARCH_MIPS64 = SCMP_ARCH_MIPS64;
  62. const uint32_t C_ARCH_MIPS64N32 = SCMP_ARCH_MIPS64N32;
  63. const uint32_t C_ARCH_MIPSEL = SCMP_ARCH_MIPSEL;
  64. const uint32_t C_ARCH_MIPSEL64 = SCMP_ARCH_MIPSEL64;
  65. const uint32_t C_ARCH_MIPSEL64N32 = SCMP_ARCH_MIPSEL64N32;
  66. const uint32_t C_ARCH_PPC = SCMP_ARCH_PPC;
  67. const uint32_t C_ARCH_PPC64 = SCMP_ARCH_PPC64;
  68. const uint32_t C_ARCH_PPC64LE = SCMP_ARCH_PPC64LE;
  69. const uint32_t C_ARCH_S390 = SCMP_ARCH_S390;
  70. const uint32_t C_ARCH_S390X = SCMP_ARCH_S390X;
  71. const uint32_t C_ARCH_PARISC = SCMP_ARCH_PARISC;
  72. const uint32_t C_ARCH_PARISC64 = SCMP_ARCH_PARISC64;
  73. const uint32_t C_ARCH_RISCV64 = SCMP_ARCH_RISCV64;
  74. #ifndef SCMP_ACT_LOG
  75. #define SCMP_ACT_LOG 0x7ffc0000U
  76. #endif
  77. #ifndef SCMP_ACT_KILL_PROCESS
  78. #define SCMP_ACT_KILL_PROCESS 0x80000000U
  79. #endif
  80. #ifndef SCMP_ACT_KILL_THREAD
  81. #define SCMP_ACT_KILL_THREAD 0x00000000U
  82. #endif
  83. #ifndef SCMP_ACT_NOTIFY
  84. #define SCMP_ACT_NOTIFY 0x7fc00000U
  85. #endif
  86. const uint32_t C_ACT_KILL = SCMP_ACT_KILL;
  87. const uint32_t C_ACT_KILL_PROCESS = SCMP_ACT_KILL_PROCESS;
  88. const uint32_t C_ACT_KILL_THREAD = SCMP_ACT_KILL_THREAD;
  89. const uint32_t C_ACT_TRAP = SCMP_ACT_TRAP;
  90. const uint32_t C_ACT_ERRNO = SCMP_ACT_ERRNO(0);
  91. const uint32_t C_ACT_TRACE = SCMP_ACT_TRACE(0);
  92. const uint32_t C_ACT_LOG = SCMP_ACT_LOG;
  93. const uint32_t C_ACT_ALLOW = SCMP_ACT_ALLOW;
  94. const uint32_t C_ACT_NOTIFY = SCMP_ACT_NOTIFY;
  95. // The libseccomp SCMP_FLTATR_CTL_LOG member of the scmp_filter_attr enum was
  96. // added in v2.4.0
  97. #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4
  98. #define SCMP_FLTATR_CTL_LOG _SCMP_FLTATR_MIN
  99. #endif
  100. // The following SCMP_FLTATR_* were added in libseccomp v2.5.0.
  101. #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
  102. #define SCMP_FLTATR_CTL_SSB _SCMP_FLTATR_MIN
  103. #define SCMP_FLTATR_CTL_OPTIMIZE _SCMP_FLTATR_MIN
  104. #define SCMP_FLTATR_API_SYSRAWRC _SCMP_FLTATR_MIN
  105. #endif
  106. const uint32_t C_ATTRIBUTE_DEFAULT = (uint32_t)SCMP_FLTATR_ACT_DEFAULT;
  107. const uint32_t C_ATTRIBUTE_BADARCH = (uint32_t)SCMP_FLTATR_ACT_BADARCH;
  108. const uint32_t C_ATTRIBUTE_NNP = (uint32_t)SCMP_FLTATR_CTL_NNP;
  109. const uint32_t C_ATTRIBUTE_TSYNC = (uint32_t)SCMP_FLTATR_CTL_TSYNC;
  110. const uint32_t C_ATTRIBUTE_LOG = (uint32_t)SCMP_FLTATR_CTL_LOG;
  111. const uint32_t C_ATTRIBUTE_SSB = (uint32_t)SCMP_FLTATR_CTL_SSB;
  112. const uint32_t C_ATTRIBUTE_OPTIMIZE = (uint32_t)SCMP_FLTATR_CTL_OPTIMIZE;
  113. const uint32_t C_ATTRIBUTE_SYSRAWRC = (uint32_t)SCMP_FLTATR_API_SYSRAWRC;
  114. const int C_CMP_NE = (int)SCMP_CMP_NE;
  115. const int C_CMP_LT = (int)SCMP_CMP_LT;
  116. const int C_CMP_LE = (int)SCMP_CMP_LE;
  117. const int C_CMP_EQ = (int)SCMP_CMP_EQ;
  118. const int C_CMP_GE = (int)SCMP_CMP_GE;
  119. const int C_CMP_GT = (int)SCMP_CMP_GT;
  120. const int C_CMP_MASKED_EQ = (int)SCMP_CMP_MASKED_EQ;
  121. const int C_VERSION_MAJOR = SCMP_VER_MAJOR;
  122. const int C_VERSION_MINOR = SCMP_VER_MINOR;
  123. const int C_VERSION_MICRO = SCMP_VER_MICRO;
  124. #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR >= 3
  125. unsigned int get_major_version()
  126. {
  127. return seccomp_version()->major;
  128. }
  129. unsigned int get_minor_version()
  130. {
  131. return seccomp_version()->minor;
  132. }
  133. unsigned int get_micro_version()
  134. {
  135. return seccomp_version()->micro;
  136. }
  137. #else
  138. unsigned int get_major_version()
  139. {
  140. return (unsigned int)C_VERSION_MAJOR;
  141. }
  142. unsigned int get_minor_version()
  143. {
  144. return (unsigned int)C_VERSION_MINOR;
  145. }
  146. unsigned int get_micro_version()
  147. {
  148. return (unsigned int)C_VERSION_MICRO;
  149. }
  150. #endif
  151. // The libseccomp API level functions were added in v2.4.0
  152. #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 4
  153. const unsigned int seccomp_api_get(void)
  154. {
  155. // libseccomp-golang requires libseccomp v2.2.0, at a minimum, which
  156. // supported API level 2. However, the kernel may not support API level
  157. // 2 constructs which are the seccomp() system call and the TSYNC
  158. // filter flag. Return the "reserved" value of 0 here to indicate that
  159. // proper API level support is not available in libseccomp.
  160. return 0;
  161. }
  162. int seccomp_api_set(unsigned int level)
  163. {
  164. return -EOPNOTSUPP;
  165. }
  166. #endif
  167. typedef struct scmp_arg_cmp* scmp_cast_t;
  168. void* make_arg_cmp_array(unsigned int length)
  169. {
  170. return calloc(length, sizeof(struct scmp_arg_cmp));
  171. }
  172. // Wrapper to add an scmp_arg_cmp struct to an existing arg_cmp array
  173. void add_struct_arg_cmp(
  174. struct scmp_arg_cmp* arr,
  175. unsigned int pos,
  176. unsigned int arg,
  177. int compare,
  178. uint64_t a,
  179. uint64_t b
  180. )
  181. {
  182. arr[pos].arg = arg;
  183. arr[pos].op = compare;
  184. arr[pos].datum_a = a;
  185. arr[pos].datum_b = b;
  186. return;
  187. }
  188. // The seccomp notify API functions were added in v2.5.0
  189. #if SCMP_VER_MAJOR == 2 && SCMP_VER_MINOR < 5
  190. struct seccomp_data {
  191. int nr;
  192. __u32 arch;
  193. __u64 instruction_pointer;
  194. __u64 args[6];
  195. };
  196. struct seccomp_notif {
  197. __u64 id;
  198. __u32 pid;
  199. __u32 flags;
  200. struct seccomp_data data;
  201. };
  202. struct seccomp_notif_resp {
  203. __u64 id;
  204. __s64 val;
  205. __s32 error;
  206. __u32 flags;
  207. };
  208. int seccomp_notify_alloc(struct seccomp_notif **req, struct seccomp_notif_resp **resp) {
  209. return -EOPNOTSUPP;
  210. }
  211. int seccomp_notify_fd(const scmp_filter_ctx ctx) {
  212. return -EOPNOTSUPP;
  213. }
  214. void seccomp_notify_free(struct seccomp_notif *req, struct seccomp_notif_resp *resp) {
  215. }
  216. int seccomp_notify_id_valid(int fd, uint64_t id) {
  217. return -EOPNOTSUPP;
  218. }
  219. int seccomp_notify_receive(int fd, struct seccomp_notif *req) {
  220. return -EOPNOTSUPP;
  221. }
  222. int seccomp_notify_respond(int fd, struct seccomp_notif_resp *resp) {
  223. return -EOPNOTSUPP;
  224. }
  225. #endif
  226. */
  227. import "C"
  228. // Nonexported types
  229. type scmpFilterAttr uint32
  230. // Nonexported constants
  231. const (
  232. filterAttrActDefault scmpFilterAttr = iota
  233. filterAttrActBadArch
  234. filterAttrNNP
  235. filterAttrTsync
  236. filterAttrLog
  237. filterAttrSSB
  238. filterAttrOptimize
  239. filterAttrRawRC
  240. )
  241. const (
  242. // An error return from certain libseccomp functions
  243. scmpError C.int = -1
  244. // Comparison boundaries to check for architecture validity
  245. archStart ScmpArch = ArchNative
  246. archEnd ScmpArch = ArchRISCV64
  247. // Comparison boundaries to check for action validity
  248. actionStart ScmpAction = ActKillThread
  249. actionEnd ScmpAction = ActKillProcess
  250. // Comparison boundaries to check for comparison operator validity
  251. compareOpStart ScmpCompareOp = CompareNotEqual
  252. compareOpEnd ScmpCompareOp = CompareMaskedEqual
  253. )
  254. var (
  255. // errBadFilter is thrown on bad filter context.
  256. errBadFilter = errors.New("filter is invalid or uninitialized")
  257. errDefAction = errors.New("requested action matches default action of filter")
  258. // Constants representing library major, minor, and micro versions
  259. verMajor = uint(C.get_major_version())
  260. verMinor = uint(C.get_minor_version())
  261. verMicro = uint(C.get_micro_version())
  262. )
  263. // Nonexported functions
  264. // checkVersion returns an error if the libseccomp version being used
  265. // is less than the one specified by major, minor, and micro arguments.
  266. // Argument op is an arbitrary non-empty operation description, which
  267. // is used as a part of the error message returned.
  268. //
  269. // Most users should use checkAPI instead.
  270. func checkVersion(op string, major, minor, micro uint) error {
  271. if (verMajor > major) ||
  272. (verMajor == major && verMinor > minor) ||
  273. (verMajor == major && verMinor == minor && verMicro >= micro) {
  274. return nil
  275. }
  276. return &VersionError{
  277. op: op,
  278. major: major,
  279. minor: minor,
  280. micro: micro,
  281. }
  282. }
  283. func ensureSupportedVersion() error {
  284. return checkVersion("seccomp", 2, 3, 1)
  285. }
  286. // Get the API level
  287. func getAPI() (uint, error) {
  288. api := C.seccomp_api_get()
  289. if api == 0 {
  290. return 0, fmt.Errorf("API level operations are not supported")
  291. }
  292. return uint(api), nil
  293. }
  294. // Set the API level
  295. func setAPI(api uint) error {
  296. if retCode := C.seccomp_api_set(C.uint(api)); retCode != 0 {
  297. if errRc(retCode) == syscall.EOPNOTSUPP {
  298. return fmt.Errorf("API level operations are not supported")
  299. }
  300. return fmt.Errorf("could not set API level: %v", retCode)
  301. }
  302. return nil
  303. }
  304. // Filter helpers
  305. // Filter finalizer - ensure that kernel context for filters is freed
  306. func filterFinalizer(f *ScmpFilter) {
  307. f.Release()
  308. }
  309. func errRc(rc C.int) error {
  310. return syscall.Errno(-1 * rc)
  311. }
  312. // Get a raw filter attribute
  313. func (f *ScmpFilter) getFilterAttr(attr scmpFilterAttr) (C.uint32_t, error) {
  314. f.lock.Lock()
  315. defer f.lock.Unlock()
  316. if !f.valid {
  317. return 0x0, errBadFilter
  318. }
  319. var attribute C.uint32_t
  320. retCode := C.seccomp_attr_get(f.filterCtx, attr.toNative(), &attribute)
  321. if retCode != 0 {
  322. return 0x0, errRc(retCode)
  323. }
  324. return attribute, nil
  325. }
  326. // Set a raw filter attribute
  327. func (f *ScmpFilter) setFilterAttr(attr scmpFilterAttr, value C.uint32_t) error {
  328. f.lock.Lock()
  329. defer f.lock.Unlock()
  330. if !f.valid {
  331. return errBadFilter
  332. }
  333. retCode := C.seccomp_attr_set(f.filterCtx, attr.toNative(), value)
  334. if retCode != 0 {
  335. return errRc(retCode)
  336. }
  337. return nil
  338. }
  339. // DOES NOT LOCK OR CHECK VALIDITY
  340. // Assumes caller has already done this
  341. // Wrapper for seccomp_rule_add_... functions
  342. func (f *ScmpFilter) addRuleWrapper(call ScmpSyscall, action ScmpAction, exact bool, length C.uint, cond C.scmp_cast_t) error {
  343. if length != 0 && cond == nil {
  344. return fmt.Errorf("null conditions list, but length is nonzero")
  345. }
  346. var retCode C.int
  347. if exact {
  348. retCode = C.seccomp_rule_add_exact_array(f.filterCtx, action.toNative(), C.int(call), length, cond)
  349. } else {
  350. retCode = C.seccomp_rule_add_array(f.filterCtx, action.toNative(), C.int(call), length, cond)
  351. }
  352. if retCode != 0 {
  353. switch e := errRc(retCode); e {
  354. case syscall.EFAULT:
  355. return fmt.Errorf("unrecognized syscall %#x", int32(call))
  356. // libseccomp >= v2.5.0 returns EACCES, older versions return EPERM.
  357. // TODO: remove EPERM once libseccomp < v2.5.0 is not supported.
  358. case syscall.EPERM, syscall.EACCES:
  359. return errDefAction
  360. case syscall.EINVAL:
  361. return fmt.Errorf("two checks on same syscall argument")
  362. default:
  363. return e
  364. }
  365. }
  366. return nil
  367. }
  368. // Generic add function for filter rules
  369. func (f *ScmpFilter) addRuleGeneric(call ScmpSyscall, action ScmpAction, exact bool, conds []ScmpCondition) error {
  370. f.lock.Lock()
  371. defer f.lock.Unlock()
  372. if !f.valid {
  373. return errBadFilter
  374. }
  375. if len(conds) == 0 {
  376. if err := f.addRuleWrapper(call, action, exact, 0, nil); err != nil {
  377. return err
  378. }
  379. } else {
  380. argsArr := C.make_arg_cmp_array(C.uint(len(conds)))
  381. if argsArr == nil {
  382. return fmt.Errorf("error allocating memory for conditions")
  383. }
  384. defer C.free(argsArr)
  385. for i, cond := range conds {
  386. C.add_struct_arg_cmp(C.scmp_cast_t(argsArr), C.uint(i),
  387. C.uint(cond.Argument), cond.Op.toNative(),
  388. C.uint64_t(cond.Operand1), C.uint64_t(cond.Operand2))
  389. }
  390. if err := f.addRuleWrapper(call, action, exact, C.uint(len(conds)), C.scmp_cast_t(argsArr)); err != nil {
  391. return err
  392. }
  393. }
  394. return nil
  395. }
  396. // Generic Helpers
  397. // Helper - Sanitize Arch token input
  398. func sanitizeArch(in ScmpArch) error {
  399. if in < archStart || in > archEnd {
  400. return fmt.Errorf("unrecognized architecture %#x", uint(in))
  401. }
  402. if in.toNative() == C.C_ARCH_BAD {
  403. return fmt.Errorf("architecture %v is not supported on this version of the library", in)
  404. }
  405. return nil
  406. }
  407. func sanitizeAction(in ScmpAction) error {
  408. inTmp := in & 0x0000FFFF
  409. if inTmp < actionStart || inTmp > actionEnd {
  410. return fmt.Errorf("unrecognized action %#x", uint(inTmp))
  411. }
  412. if inTmp != ActTrace && inTmp != ActErrno && (in&0xFFFF0000) != 0 {
  413. return fmt.Errorf("highest 16 bits must be zeroed except for Trace and Errno")
  414. }
  415. return nil
  416. }
  417. func sanitizeCompareOp(in ScmpCompareOp) error {
  418. if in < compareOpStart || in > compareOpEnd {
  419. return fmt.Errorf("unrecognized comparison operator %#x", uint(in))
  420. }
  421. return nil
  422. }
  423. func archFromNative(a C.uint32_t) (ScmpArch, error) {
  424. switch a {
  425. case C.C_ARCH_X86:
  426. return ArchX86, nil
  427. case C.C_ARCH_X86_64:
  428. return ArchAMD64, nil
  429. case C.C_ARCH_X32:
  430. return ArchX32, nil
  431. case C.C_ARCH_ARM:
  432. return ArchARM, nil
  433. case C.C_ARCH_NATIVE:
  434. return ArchNative, nil
  435. case C.C_ARCH_AARCH64:
  436. return ArchARM64, nil
  437. case C.C_ARCH_MIPS:
  438. return ArchMIPS, nil
  439. case C.C_ARCH_MIPS64:
  440. return ArchMIPS64, nil
  441. case C.C_ARCH_MIPS64N32:
  442. return ArchMIPS64N32, nil
  443. case C.C_ARCH_MIPSEL:
  444. return ArchMIPSEL, nil
  445. case C.C_ARCH_MIPSEL64:
  446. return ArchMIPSEL64, nil
  447. case C.C_ARCH_MIPSEL64N32:
  448. return ArchMIPSEL64N32, nil
  449. case C.C_ARCH_PPC:
  450. return ArchPPC, nil
  451. case C.C_ARCH_PPC64:
  452. return ArchPPC64, nil
  453. case C.C_ARCH_PPC64LE:
  454. return ArchPPC64LE, nil
  455. case C.C_ARCH_S390:
  456. return ArchS390, nil
  457. case C.C_ARCH_S390X:
  458. return ArchS390X, nil
  459. case C.C_ARCH_PARISC:
  460. return ArchPARISC, nil
  461. case C.C_ARCH_PARISC64:
  462. return ArchPARISC64, nil
  463. case C.C_ARCH_RISCV64:
  464. return ArchRISCV64, nil
  465. default:
  466. return 0x0, fmt.Errorf("unrecognized architecture %#x", uint32(a))
  467. }
  468. }
  469. // Only use with sanitized arches, no error handling
  470. func (a ScmpArch) toNative() C.uint32_t {
  471. switch a {
  472. case ArchX86:
  473. return C.C_ARCH_X86
  474. case ArchAMD64:
  475. return C.C_ARCH_X86_64
  476. case ArchX32:
  477. return C.C_ARCH_X32
  478. case ArchARM:
  479. return C.C_ARCH_ARM
  480. case ArchARM64:
  481. return C.C_ARCH_AARCH64
  482. case ArchMIPS:
  483. return C.C_ARCH_MIPS
  484. case ArchMIPS64:
  485. return C.C_ARCH_MIPS64
  486. case ArchMIPS64N32:
  487. return C.C_ARCH_MIPS64N32
  488. case ArchMIPSEL:
  489. return C.C_ARCH_MIPSEL
  490. case ArchMIPSEL64:
  491. return C.C_ARCH_MIPSEL64
  492. case ArchMIPSEL64N32:
  493. return C.C_ARCH_MIPSEL64N32
  494. case ArchPPC:
  495. return C.C_ARCH_PPC
  496. case ArchPPC64:
  497. return C.C_ARCH_PPC64
  498. case ArchPPC64LE:
  499. return C.C_ARCH_PPC64LE
  500. case ArchS390:
  501. return C.C_ARCH_S390
  502. case ArchS390X:
  503. return C.C_ARCH_S390X
  504. case ArchPARISC:
  505. return C.C_ARCH_PARISC
  506. case ArchPARISC64:
  507. return C.C_ARCH_PARISC64
  508. case ArchRISCV64:
  509. return C.C_ARCH_RISCV64
  510. case ArchNative:
  511. return C.C_ARCH_NATIVE
  512. default:
  513. return 0x0
  514. }
  515. }
  516. // Only use with sanitized ops, no error handling
  517. func (a ScmpCompareOp) toNative() C.int {
  518. switch a {
  519. case CompareNotEqual:
  520. return C.C_CMP_NE
  521. case CompareLess:
  522. return C.C_CMP_LT
  523. case CompareLessOrEqual:
  524. return C.C_CMP_LE
  525. case CompareEqual:
  526. return C.C_CMP_EQ
  527. case CompareGreaterEqual:
  528. return C.C_CMP_GE
  529. case CompareGreater:
  530. return C.C_CMP_GT
  531. case CompareMaskedEqual:
  532. return C.C_CMP_MASKED_EQ
  533. default:
  534. return 0x0
  535. }
  536. }
  537. func actionFromNative(a C.uint32_t) (ScmpAction, error) {
  538. aTmp := a & 0xFFFF
  539. switch a & 0xFFFF0000 {
  540. case C.C_ACT_KILL_PROCESS:
  541. return ActKillProcess, nil
  542. case C.C_ACT_KILL_THREAD:
  543. return ActKillThread, nil
  544. case C.C_ACT_TRAP:
  545. return ActTrap, nil
  546. case C.C_ACT_ERRNO:
  547. return ActErrno.SetReturnCode(int16(aTmp)), nil
  548. case C.C_ACT_TRACE:
  549. return ActTrace.SetReturnCode(int16(aTmp)), nil
  550. case C.C_ACT_LOG:
  551. return ActLog, nil
  552. case C.C_ACT_ALLOW:
  553. return ActAllow, nil
  554. case C.C_ACT_NOTIFY:
  555. return ActNotify, nil
  556. default:
  557. return 0x0, fmt.Errorf("unrecognized action %#x", uint32(a))
  558. }
  559. }
  560. // Only use with sanitized actions, no error handling
  561. func (a ScmpAction) toNative() C.uint32_t {
  562. switch a & 0xFFFF {
  563. case ActKillProcess:
  564. return C.C_ACT_KILL_PROCESS
  565. case ActKillThread:
  566. return C.C_ACT_KILL_THREAD
  567. case ActTrap:
  568. return C.C_ACT_TRAP
  569. case ActErrno:
  570. return C.C_ACT_ERRNO | (C.uint32_t(a) >> 16)
  571. case ActTrace:
  572. return C.C_ACT_TRACE | (C.uint32_t(a) >> 16)
  573. case ActLog:
  574. return C.C_ACT_LOG
  575. case ActAllow:
  576. return C.C_ACT_ALLOW
  577. case ActNotify:
  578. return C.C_ACT_NOTIFY
  579. default:
  580. return 0x0
  581. }
  582. }
  583. // Internal only, assumes safe attribute
  584. func (a scmpFilterAttr) toNative() uint32 {
  585. switch a {
  586. case filterAttrActDefault:
  587. return uint32(C.C_ATTRIBUTE_DEFAULT)
  588. case filterAttrActBadArch:
  589. return uint32(C.C_ATTRIBUTE_BADARCH)
  590. case filterAttrNNP:
  591. return uint32(C.C_ATTRIBUTE_NNP)
  592. case filterAttrTsync:
  593. return uint32(C.C_ATTRIBUTE_TSYNC)
  594. case filterAttrLog:
  595. return uint32(C.C_ATTRIBUTE_LOG)
  596. case filterAttrSSB:
  597. return uint32(C.C_ATTRIBUTE_SSB)
  598. case filterAttrOptimize:
  599. return uint32(C.C_ATTRIBUTE_OPTIMIZE)
  600. case filterAttrRawRC:
  601. return uint32(C.C_ATTRIBUTE_SYSRAWRC)
  602. default:
  603. return 0x0
  604. }
  605. }
  606. func syscallFromNative(a C.int) ScmpSyscall {
  607. return ScmpSyscall(a)
  608. }
  609. func notifReqFromNative(req *C.struct_seccomp_notif) (*ScmpNotifReq, error) {
  610. scmpArgs := make([]uint64, 6)
  611. for i := 0; i < len(scmpArgs); i++ {
  612. scmpArgs[i] = uint64(req.data.args[i])
  613. }
  614. arch, err := archFromNative(req.data.arch)
  615. if err != nil {
  616. return nil, err
  617. }
  618. scmpData := ScmpNotifData{
  619. Syscall: syscallFromNative(req.data.nr),
  620. Arch: arch,
  621. InstrPointer: uint64(req.data.instruction_pointer),
  622. Args: scmpArgs,
  623. }
  624. scmpReq := &ScmpNotifReq{
  625. ID: uint64(req.id),
  626. Pid: uint32(req.pid),
  627. Flags: uint32(req.flags),
  628. Data: scmpData,
  629. }
  630. return scmpReq, nil
  631. }
  632. func (scmpResp *ScmpNotifResp) toNative(resp *C.struct_seccomp_notif_resp) {
  633. resp.id = C.__u64(scmpResp.ID)
  634. resp.val = C.__s64(scmpResp.Val)
  635. resp.error = (C.__s32(scmpResp.Error) * -1) // kernel requires a negated value
  636. resp.flags = C.__u32(scmpResp.Flags)
  637. }
  638. // checkAPI checks that both the API level and the seccomp version is equal to
  639. // or greater than the specified minLevel and major, minor, micro,
  640. // respectively, and returns an error otherwise. Argument op is an arbitrary
  641. // non-empty operation description, used as a part of the error message
  642. // returned.
  643. func checkAPI(op string, minLevel uint, major, minor, micro uint) error {
  644. // Ignore error from getAPI, as it returns level == 0 in case of error.
  645. level, _ := getAPI()
  646. if level >= minLevel {
  647. return checkVersion(op, major, minor, micro)
  648. }
  649. return &VersionError{
  650. op: op,
  651. curAPI: level,
  652. minAPI: minLevel,
  653. major: major,
  654. minor: minor,
  655. micro: micro,
  656. }
  657. }
  658. // Userspace Notification API
  659. // Calls to C.seccomp_notify* hidden from seccomp.go
  660. func notifSupported() error {
  661. return checkAPI("seccomp notification", 6, 2, 5, 0)
  662. }
  663. func (f *ScmpFilter) getNotifFd() (ScmpFd, error) {
  664. f.lock.Lock()
  665. defer f.lock.Unlock()
  666. if !f.valid {
  667. return -1, errBadFilter
  668. }
  669. if err := notifSupported(); err != nil {
  670. return -1, err
  671. }
  672. fd := C.seccomp_notify_fd(f.filterCtx)
  673. return ScmpFd(fd), nil
  674. }
  675. func notifReceive(fd ScmpFd) (*ScmpNotifReq, error) {
  676. var req *C.struct_seccomp_notif
  677. var resp *C.struct_seccomp_notif_resp
  678. if err := notifSupported(); err != nil {
  679. return nil, err
  680. }
  681. // we only use the request here; the response is unused
  682. if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
  683. return nil, errRc(retCode)
  684. }
  685. defer func() {
  686. C.seccomp_notify_free(req, resp)
  687. }()
  688. for {
  689. retCode, errno := C.seccomp_notify_receive(C.int(fd), req)
  690. if retCode == 0 {
  691. break
  692. }
  693. if errno == syscall.EINTR {
  694. continue
  695. }
  696. if errno == syscall.ENOENT {
  697. return nil, errno
  698. }
  699. return nil, errRc(retCode)
  700. }
  701. return notifReqFromNative(req)
  702. }
  703. func notifRespond(fd ScmpFd, scmpResp *ScmpNotifResp) error {
  704. var req *C.struct_seccomp_notif
  705. var resp *C.struct_seccomp_notif_resp
  706. if err := notifSupported(); err != nil {
  707. return err
  708. }
  709. // we only use the response here; the request is discarded
  710. if retCode := C.seccomp_notify_alloc(&req, &resp); retCode != 0 {
  711. return errRc(retCode)
  712. }
  713. defer func() {
  714. C.seccomp_notify_free(req, resp)
  715. }()
  716. scmpResp.toNative(resp)
  717. for {
  718. retCode, errno := C.seccomp_notify_respond(C.int(fd), resp)
  719. if retCode == 0 {
  720. break
  721. }
  722. if errno == syscall.EINTR {
  723. continue
  724. }
  725. if errno == syscall.ENOENT {
  726. return errno
  727. }
  728. return errRc(retCode)
  729. }
  730. return nil
  731. }
  732. func notifIDValid(fd ScmpFd, id uint64) error {
  733. if err := notifSupported(); err != nil {
  734. return err
  735. }
  736. for {
  737. retCode, errno := C.seccomp_notify_id_valid(C.int(fd), C.uint64_t(id))
  738. if retCode == 0 {
  739. break
  740. }
  741. if errno == syscall.EINTR {
  742. continue
  743. }
  744. if errno == syscall.ENOENT {
  745. return errno
  746. }
  747. return errRc(retCode)
  748. }
  749. return nil
  750. }