script_core 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (191) hide show
  1. checksums.yaml +4 -4
  2. data/ext/enterprise_script_service/libseccomp/.travis.yml +21 -7
  3. data/ext/enterprise_script_service/libseccomp/CHANGELOG +22 -0
  4. data/ext/enterprise_script_service/libseccomp/CONTRIBUTING.md +37 -26
  5. data/ext/enterprise_script_service/libseccomp/CREDITS +8 -0
  6. data/ext/enterprise_script_service/libseccomp/README.md +3 -1
  7. data/ext/enterprise_script_service/libseccomp/configure.ac +13 -8
  8. data/ext/enterprise_script_service/libseccomp/doc/Makefile.am +6 -0
  9. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_api_get.3 +12 -2
  10. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_arch_add.3 +38 -6
  11. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_attr_set.3 +53 -2
  12. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_export_bpf.3 +20 -2
  13. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_init.3 +9 -2
  14. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_load.3 +32 -2
  15. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_merge.3 +16 -2
  16. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_notify_alloc.3 +113 -0
  17. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_notify_fd.3 +1 -0
  18. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_notify_free.3 +1 -0
  19. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_notify_id_valid.3 +1 -0
  20. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_notify_receive.3 +1 -0
  21. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_notify_respond.3 +1 -0
  22. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_rule_add.3 +64 -3
  23. data/ext/enterprise_script_service/libseccomp/doc/man/man3/seccomp_syscall_priority.3 +18 -3
  24. data/ext/enterprise_script_service/libseccomp/include/seccomp-syscalls.h +12 -0
  25. data/ext/enterprise_script_service/libseccomp/include/seccomp.h.in +116 -0
  26. data/ext/enterprise_script_service/libseccomp/src/.gitignore +2 -0
  27. data/ext/enterprise_script_service/libseccomp/src/Makefile.am +31 -17
  28. data/ext/enterprise_script_service/libseccomp/src/api.c +254 -58
  29. data/ext/enterprise_script_service/libseccomp/src/arch-aarch64.h +1 -9
  30. data/ext/enterprise_script_service/libseccomp/src/arch-arm.c +47 -2
  31. data/ext/enterprise_script_service/libseccomp/src/arch-arm.h +1 -9
  32. data/ext/enterprise_script_service/libseccomp/src/arch-gperf-generate +40 -0
  33. data/ext/enterprise_script_service/libseccomp/src/arch-mips.c +41 -4
  34. data/ext/enterprise_script_service/libseccomp/src/arch-mips.h +2 -10
  35. data/ext/enterprise_script_service/libseccomp/src/arch-mips64.c +41 -4
  36. data/ext/enterprise_script_service/libseccomp/src/arch-mips64.h +3 -11
  37. data/ext/enterprise_script_service/libseccomp/src/arch-mips64n32.c +41 -4
  38. data/ext/enterprise_script_service/libseccomp/src/arch-mips64n32.h +2 -10
  39. data/ext/enterprise_script_service/libseccomp/src/arch-parisc.h +1 -10
  40. data/ext/enterprise_script_service/libseccomp/src/arch-parisc64.c +3 -3
  41. data/ext/enterprise_script_service/libseccomp/src/arch-parisc64.h +29 -0
  42. data/ext/enterprise_script_service/libseccomp/src/arch-ppc.h +1 -9
  43. data/ext/enterprise_script_service/libseccomp/src/arch-ppc64.c +606 -8
  44. data/ext/enterprise_script_service/libseccomp/src/arch-ppc64.h +2 -10
  45. data/ext/enterprise_script_service/libseccomp/src/arch-riscv64.c +31 -0
  46. data/ext/enterprise_script_service/libseccomp/src/arch-riscv64.h +22 -0
  47. data/ext/enterprise_script_service/libseccomp/src/arch-s390.c +171 -12
  48. data/ext/enterprise_script_service/libseccomp/src/arch-s390.h +1 -17
  49. data/ext/enterprise_script_service/libseccomp/src/arch-s390x.c +166 -10
  50. data/ext/enterprise_script_service/libseccomp/src/arch-s390x.h +1 -20
  51. data/ext/enterprise_script_service/libseccomp/src/arch-syscall-dump.c +8 -1
  52. data/ext/enterprise_script_service/libseccomp/src/arch-syscall-validate +359 -143
  53. data/ext/enterprise_script_service/libseccomp/src/arch-x32.c +36 -2
  54. data/ext/enterprise_script_service/libseccomp/src/arch-x32.h +2 -10
  55. data/ext/enterprise_script_service/libseccomp/src/arch-x86.c +172 -10
  56. data/ext/enterprise_script_service/libseccomp/src/arch-x86.h +1 -14
  57. data/ext/enterprise_script_service/libseccomp/src/arch-x86_64.h +1 -9
  58. data/ext/enterprise_script_service/libseccomp/src/arch.c +11 -3
  59. data/ext/enterprise_script_service/libseccomp/src/arch.h +7 -0
  60. data/ext/enterprise_script_service/libseccomp/src/db.c +268 -57
  61. data/ext/enterprise_script_service/libseccomp/src/db.h +16 -2
  62. data/ext/enterprise_script_service/libseccomp/src/gen_bpf.c +503 -148
  63. data/ext/enterprise_script_service/libseccomp/src/gen_bpf.h +2 -1
  64. data/ext/enterprise_script_service/libseccomp/src/gen_pfc.c +165 -37
  65. data/ext/enterprise_script_service/libseccomp/src/python/libseccomp.pxd +37 -1
  66. data/ext/enterprise_script_service/libseccomp/src/python/seccomp.pyx +295 -5
  67. data/ext/enterprise_script_service/libseccomp/src/syscalls.c +56 -0
  68. data/ext/enterprise_script_service/libseccomp/src/syscalls.csv +470 -0
  69. data/ext/enterprise_script_service/libseccomp/src/syscalls.h +62 -0
  70. data/ext/enterprise_script_service/libseccomp/src/syscalls.perf.template +82 -0
  71. data/ext/enterprise_script_service/libseccomp/src/system.c +196 -16
  72. data/ext/enterprise_script_service/libseccomp/src/system.h +68 -13
  73. data/ext/enterprise_script_service/libseccomp/tests/.gitignore +9 -2
  74. data/ext/enterprise_script_service/libseccomp/tests/06-sim-actions.tests +1 -1
  75. data/ext/enterprise_script_service/libseccomp/tests/11-basic-basic_errors.c +5 -5
  76. data/ext/enterprise_script_service/libseccomp/tests/13-basic-attrs.c +35 -1
  77. data/ext/enterprise_script_service/libseccomp/tests/13-basic-attrs.py +10 -1
  78. data/ext/enterprise_script_service/libseccomp/tests/15-basic-resolver.c +1 -0
  79. data/ext/enterprise_script_service/libseccomp/tests/16-sim-arch_basic.c +12 -0
  80. data/ext/enterprise_script_service/libseccomp/tests/16-sim-arch_basic.py +1 -0
  81. data/ext/enterprise_script_service/libseccomp/tests/{18-sim-basic_whitelist.c → 18-sim-basic_allowlist.c} +0 -0
  82. data/ext/enterprise_script_service/libseccomp/tests/{18-sim-basic_whitelist.py → 18-sim-basic_allowlist.py} +0 -0
  83. data/ext/enterprise_script_service/libseccomp/tests/18-sim-basic_allowlist.tests +32 -0
  84. data/ext/enterprise_script_service/libseccomp/tests/23-sim-arch_all_le_basic.c +3 -0
  85. data/ext/enterprise_script_service/libseccomp/tests/23-sim-arch_all_le_basic.py +1 -0
  86. data/ext/enterprise_script_service/libseccomp/tests/30-sim-socket_syscalls.c +3 -0
  87. data/ext/enterprise_script_service/libseccomp/tests/30-sim-socket_syscalls.py +1 -0
  88. data/ext/enterprise_script_service/libseccomp/tests/30-sim-socket_syscalls.tests +33 -17
  89. data/ext/enterprise_script_service/libseccomp/tests/{34-sim-basic_blacklist.c → 34-sim-basic_denylist.c} +0 -0
  90. data/ext/enterprise_script_service/libseccomp/tests/{34-sim-basic_blacklist.py → 34-sim-basic_denylist.py} +0 -0
  91. data/ext/enterprise_script_service/libseccomp/tests/34-sim-basic_denylist.tests +32 -0
  92. data/ext/enterprise_script_service/libseccomp/tests/36-sim-ipc_syscalls.c +3 -0
  93. data/ext/enterprise_script_service/libseccomp/tests/36-sim-ipc_syscalls.py +1 -0
  94. data/ext/enterprise_script_service/libseccomp/tests/36-sim-ipc_syscalls.tests +25 -25
  95. data/ext/enterprise_script_service/libseccomp/tests/39-basic-api_level.c +24 -3
  96. data/ext/enterprise_script_service/libseccomp/tests/39-basic-api_level.py +16 -1
  97. data/ext/enterprise_script_service/libseccomp/tests/47-live-kill_process.c +3 -3
  98. data/ext/enterprise_script_service/libseccomp/tests/51-live-user_notification.c +112 -0
  99. data/ext/enterprise_script_service/libseccomp/tests/51-live-user_notification.py +60 -0
  100. data/ext/enterprise_script_service/libseccomp/tests/51-live-user_notification.tests +11 -0
  101. data/ext/enterprise_script_service/libseccomp/tests/53-sim-binary_tree.c +156 -0
  102. data/ext/enterprise_script_service/libseccomp/tests/53-sim-binary_tree.py +95 -0
  103. data/ext/enterprise_script_service/libseccomp/tests/53-sim-binary_tree.tests +65 -0
  104. data/ext/enterprise_script_service/libseccomp/tests/54-live-binary_tree.c +128 -0
  105. data/ext/enterprise_script_service/libseccomp/tests/54-live-binary_tree.py +95 -0
  106. data/ext/enterprise_script_service/libseccomp/tests/54-live-binary_tree.tests +11 -0
  107. data/ext/enterprise_script_service/libseccomp/tests/55-basic-pfc_binary_tree.c +134 -0
  108. data/ext/enterprise_script_service/libseccomp/tests/55-basic-pfc_binary_tree.sh +46 -0
  109. data/ext/enterprise_script_service/libseccomp/tests/55-basic-pfc_binary_tree.tests +11 -0
  110. data/ext/enterprise_script_service/libseccomp/tests/56-basic-iterate_syscalls.c +90 -0
  111. data/ext/enterprise_script_service/libseccomp/tests/56-basic-iterate_syscalls.py +65 -0
  112. data/ext/enterprise_script_service/libseccomp/tests/56-basic-iterate_syscalls.tests +11 -0
  113. data/ext/enterprise_script_service/libseccomp/tests/57-basic-rawsysrc.c +64 -0
  114. data/ext/enterprise_script_service/libseccomp/tests/57-basic-rawsysrc.py +46 -0
  115. data/ext/enterprise_script_service/libseccomp/tests/57-basic-rawsysrc.tests +11 -0
  116. data/ext/enterprise_script_service/libseccomp/tests/58-live-tsync_notify.c +116 -0
  117. data/ext/enterprise_script_service/libseccomp/tests/58-live-tsync_notify.py +61 -0
  118. data/ext/enterprise_script_service/libseccomp/tests/58-live-tsync_notify.tests +11 -0
  119. data/ext/enterprise_script_service/libseccomp/tests/Makefile.am +31 -10
  120. data/ext/enterprise_script_service/libseccomp/tests/regression +6 -3
  121. data/ext/enterprise_script_service/libseccomp/tests/util.c +3 -3
  122. data/ext/enterprise_script_service/libseccomp/tools/check-syntax +1 -1
  123. data/ext/enterprise_script_service/libseccomp/tools/scmp_arch_detect.c +3 -0
  124. data/ext/enterprise_script_service/libseccomp/tools/scmp_bpf_disasm.c +4 -2
  125. data/ext/enterprise_script_service/libseccomp/tools/scmp_bpf_sim.c +2 -0
  126. data/ext/enterprise_script_service/libseccomp/tools/util.c +14 -12
  127. data/ext/enterprise_script_service/libseccomp/tools/util.h +7 -0
  128. data/ext/enterprise_script_service/mruby/.github/workflows/codeql-analysis.yml +51 -0
  129. data/ext/enterprise_script_service/mruby/Doxyfile +1 -1
  130. data/ext/enterprise_script_service/mruby/README.md +1 -1
  131. data/ext/enterprise_script_service/mruby/doc/guides/debugger.md +1 -1
  132. data/ext/enterprise_script_service/mruby/doc/limitations.md +10 -10
  133. data/ext/enterprise_script_service/mruby/include/mruby.h +13 -0
  134. data/ext/enterprise_script_service/mruby/include/mruby/boxing_word.h +0 -1
  135. data/ext/enterprise_script_service/mruby/include/mruby/proc.h +13 -8
  136. data/ext/enterprise_script_service/mruby/include/mruby/value.h +25 -29
  137. data/ext/enterprise_script_service/mruby/include/mruby/version.h +3 -3
  138. data/ext/enterprise_script_service/mruby/mrbgems/mruby-array-ext/src/array.c +5 -8
  139. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +2 -2
  140. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c +17 -10
  141. data/ext/enterprise_script_service/mruby/mrbgems/mruby-complex/mrblib/complex.rb +1 -1
  142. data/ext/enterprise_script_service/mruby/mrbgems/mruby-complex/src/complex.c +1 -2
  143. data/ext/enterprise_script_service/mruby/mrbgems/mruby-eval/src/eval.c +1 -1
  144. data/ext/enterprise_script_service/mruby/mrbgems/mruby-fiber/src/fiber.c +1 -2
  145. data/ext/enterprise_script_service/mruby/mrbgems/mruby-inline-struct/test/inline.c +3 -4
  146. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/src/file.c +1 -2
  147. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/src/file_test.c +9 -26
  148. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/src/io.c +1 -2
  149. data/ext/enterprise_script_service/mruby/mrbgems/mruby-kernel-ext/src/kernel.c +6 -8
  150. data/ext/enterprise_script_service/mruby/mrbgems/mruby-method/src/method.c +3 -4
  151. data/ext/enterprise_script_service/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c +0 -1
  152. data/ext/enterprise_script_service/mruby/mrbgems/mruby-print/src/print.c +1 -2
  153. data/ext/enterprise_script_service/mruby/mrbgems/mruby-range-ext/src/range.c +1 -3
  154. data/ext/enterprise_script_service/mruby/mrbgems/mruby-rational/mrblib/rational.rb +1 -3
  155. data/ext/enterprise_script_service/mruby/mrbgems/mruby-sprintf/src/sprintf.c +3 -3
  156. data/ext/enterprise_script_service/mruby/mrbgems/mruby-string-ext/src/string.c +1 -2
  157. data/ext/enterprise_script_service/mruby/mrbgems/mruby-struct/src/struct.c +5 -11
  158. data/ext/enterprise_script_service/mruby/mrbgems/mruby-time/src/time.c +5 -10
  159. data/ext/enterprise_script_service/mruby/mrblib/00class.rb +10 -0
  160. data/ext/enterprise_script_service/mruby/src/array.c +14 -11
  161. data/ext/enterprise_script_service/mruby/src/class.c +22 -21
  162. data/ext/enterprise_script_service/mruby/src/error.c +1 -2
  163. data/ext/enterprise_script_service/mruby/src/etc.c +0 -1
  164. data/ext/enterprise_script_service/mruby/src/gc.c +5 -5
  165. data/ext/enterprise_script_service/mruby/src/hash.c +8 -15
  166. data/ext/enterprise_script_service/mruby/src/kernel.c +4 -7
  167. data/ext/enterprise_script_service/mruby/src/numeric.c +28 -60
  168. data/ext/enterprise_script_service/mruby/src/object.c +11 -1
  169. data/ext/enterprise_script_service/mruby/src/proc.c +7 -8
  170. data/ext/enterprise_script_service/mruby/src/range.c +4 -12
  171. data/ext/enterprise_script_service/mruby/src/string.c +24 -21
  172. data/ext/enterprise_script_service/mruby/src/symbol.c +1 -2
  173. data/ext/enterprise_script_service/mruby/src/vm.c +28 -24
  174. data/ext/enterprise_script_service/mruby/test/t/kernel.rb +7 -0
  175. data/lib/script_core/version.rb +1 -1
  176. metadata +45 -21
  177. data/ext/enterprise_script_service/libseccomp/src/arch-aarch64-syscalls.c +0 -559
  178. data/ext/enterprise_script_service/libseccomp/src/arch-arm-syscalls.c +0 -570
  179. data/ext/enterprise_script_service/libseccomp/src/arch-mips-syscalls.c +0 -562
  180. data/ext/enterprise_script_service/libseccomp/src/arch-mips64-syscalls.c +0 -562
  181. data/ext/enterprise_script_service/libseccomp/src/arch-mips64n32-syscalls.c +0 -562
  182. data/ext/enterprise_script_service/libseccomp/src/arch-parisc-syscalls.c +0 -542
  183. data/ext/enterprise_script_service/libseccomp/src/arch-ppc-syscalls.c +0 -559
  184. data/ext/enterprise_script_service/libseccomp/src/arch-ppc64-syscalls.c +0 -559
  185. data/ext/enterprise_script_service/libseccomp/src/arch-s390-syscalls.c +0 -642
  186. data/ext/enterprise_script_service/libseccomp/src/arch-s390x-syscalls.c +0 -642
  187. data/ext/enterprise_script_service/libseccomp/src/arch-x32-syscalls.c +0 -558
  188. data/ext/enterprise_script_service/libseccomp/src/arch-x86-syscalls.c +0 -692
  189. data/ext/enterprise_script_service/libseccomp/src/arch-x86_64-syscalls.c +0 -559
  190. data/ext/enterprise_script_service/libseccomp/tests/18-sim-basic_whitelist.tests +0 -32
  191. data/ext/enterprise_script_service/libseccomp/tests/34-sim-basic_blacklist.tests +0 -32
@@ -36,7 +36,8 @@ struct bpf_program {
36
36
  #define BPF_PGM_SIZE(x) \
37
37
  ((x)->blk_cnt * sizeof(*((x)->blks)))
38
38
 
39
- struct bpf_program *gen_bpf_generate(const struct db_filter_col *col);
39
+ int gen_bpf_generate(const struct db_filter_col *col,
40
+ struct bpf_program **prgm_ptr);
40
41
  void gen_bpf_release(struct bpf_program *program);
41
42
 
42
43
  #endif
@@ -87,6 +87,8 @@ static const char *_pfc_arch(const struct arch_def *arch)
87
87
  return "s390x";
88
88
  case SCMP_ARCH_S390:
89
89
  return "s390";
90
+ case SCMP_ARCH_RISCV64:
91
+ return "riscv64";
90
92
  default:
91
93
  return "UNKNOWN";
92
94
  }
@@ -241,68 +243,163 @@ static void _gen_pfc_chain(const struct arch_def *arch,
241
243
  *
242
244
  */
243
245
  static void _gen_pfc_syscall(const struct arch_def *arch,
244
- const struct db_sys_list *sys, FILE *fds)
246
+ const struct db_sys_list *sys, FILE *fds,
247
+ int lvl)
245
248
  {
246
249
  unsigned int sys_num = sys->num;
247
250
  const char *sys_name = arch_syscall_resolve_num(arch, sys_num);
248
251
 
249
- _indent(fds, 1);
252
+ _indent(fds, lvl);
250
253
  fprintf(fds, "# filter for syscall \"%s\" (%u) [priority: %d]\n",
251
254
  (sys_name ? sys_name : "UNKNOWN"), sys_num, sys->priority);
252
- _indent(fds, 1);
255
+ _indent(fds, lvl);
253
256
  fprintf(fds, "if ($syscall == %u)\n", sys_num);
254
257
  if (sys->chains == NULL) {
255
- _indent(fds, 2);
258
+ _indent(fds, lvl + 1);
256
259
  _pfc_action(fds, sys->action);
257
260
  } else
258
- _gen_pfc_chain(arch, sys->chains, 2, fds);
261
+ _gen_pfc_chain(arch, sys->chains, lvl + 1, fds);
259
262
  }
260
263
 
261
- /**
262
- * Generate pseudo filter code for an architecture
263
- * @param col the seccomp filter collection
264
- * @param db the single seccomp filter
265
- * @param fds the file stream to send the output
266
- *
267
- * This function generates a pseudo filter code representation of the given
268
- * filter DB and writes it to the given output stream. Returns zero on
269
- * success, negative values on failure.
270
- *
271
- */
272
- static int _gen_pfc_arch(const struct db_filter_col *col,
273
- const struct db_filter *db, FILE *fds)
264
+ #define SYSCALLS_PER_NODE (4)
265
+ static int _get_bintree_levels(unsigned int syscall_cnt,
266
+ uint32_t optimize)
267
+ {
268
+ unsigned int i = 0, max_level;
269
+
270
+ if (optimize != 2)
271
+ /* Only use a binary tree if requested */
272
+ return 0;
273
+
274
+ do {
275
+ max_level = SYSCALLS_PER_NODE << i;
276
+ i++;
277
+ } while(max_level < syscall_cnt);
278
+
279
+ return i;
280
+ }
281
+
282
+ static int _get_bintree_syscall_num(const struct pfc_sys_list *cur,
283
+ int lookahead_cnt,
284
+ int *const num)
274
285
  {
275
- int rc = 0;
286
+ while (lookahead_cnt > 0 && cur != NULL) {
287
+ cur = cur->next;
288
+ lookahead_cnt--;
289
+ }
290
+
291
+ if (cur == NULL)
292
+ return -EFAULT;
293
+
294
+ *num = cur->sys->num;
295
+ return 0;
296
+ }
297
+
298
+ static int _sys_num_sort(struct db_sys_list *syscalls,
299
+ struct pfc_sys_list **p_head)
300
+ {
301
+ struct pfc_sys_list *p_iter = NULL, *p_new, *p_prev;
276
302
  struct db_sys_list *s_iter;
277
- struct pfc_sys_list *p_iter = NULL, *p_new, *p_head = NULL, *p_prev;
278
303
 
279
- /* sort the syscall list */
280
- db_list_foreach(s_iter, db->syscalls) {
304
+ db_list_foreach(s_iter, syscalls) {
281
305
  p_new = zmalloc(sizeof(*p_new));
282
306
  if (p_new == NULL) {
283
- rc = -ENOMEM;
284
- goto arch_return;
307
+ return -ENOMEM;
285
308
  }
286
309
  p_new->sys = s_iter;
287
310
 
288
311
  p_prev = NULL;
289
- p_iter = p_head;
312
+ p_iter = *p_head;
313
+ while (p_iter != NULL &&
314
+ s_iter->num < p_iter->sys->num) {
315
+ p_prev = p_iter;
316
+ p_iter = p_iter->next;
317
+ }
318
+ if (*p_head == NULL)
319
+ *p_head = p_new;
320
+ else if (p_prev == NULL) {
321
+ p_new->next = *p_head;
322
+ *p_head = p_new;
323
+ } else {
324
+ p_new->next = p_iter;
325
+ p_prev->next = p_new;
326
+ }
327
+ }
328
+
329
+ return 0;
330
+ }
331
+
332
+ static int _sys_priority_sort(struct db_sys_list *syscalls,
333
+ struct pfc_sys_list **p_head)
334
+ {
335
+ struct pfc_sys_list *p_iter = NULL, *p_new, *p_prev;
336
+ struct db_sys_list *s_iter;
337
+
338
+ db_list_foreach(s_iter, syscalls) {
339
+ p_new = zmalloc(sizeof(*p_new));
340
+ if (p_new == NULL) {
341
+ return -ENOMEM;
342
+ }
343
+ p_new->sys = s_iter;
344
+
345
+ p_prev = NULL;
346
+ p_iter = *p_head;
290
347
  while (p_iter != NULL &&
291
348
  s_iter->priority < p_iter->sys->priority) {
292
349
  p_prev = p_iter;
293
350
  p_iter = p_iter->next;
294
351
  }
295
- if (p_head == NULL)
296
- p_head = p_new;
352
+ if (*p_head == NULL)
353
+ *p_head = p_new;
297
354
  else if (p_prev == NULL) {
298
- p_new->next = p_head;
299
- p_head = p_new;
355
+ p_new->next = *p_head;
356
+ *p_head = p_new;
300
357
  } else {
301
358
  p_new->next = p_iter;
302
359
  p_prev->next = p_new;
303
360
  }
304
361
  }
305
362
 
363
+ return 0;
364
+ }
365
+
366
+ static int _sys_sort(struct db_sys_list *syscalls,
367
+ struct pfc_sys_list **p_head,
368
+ uint32_t optimize)
369
+ {
370
+ if (optimize != 2)
371
+ return _sys_priority_sort(syscalls, p_head);
372
+ else
373
+ /* sort by number for the binary tree */
374
+ return _sys_num_sort(syscalls, p_head);
375
+ }
376
+
377
+ /**
378
+ * Generate pseudo filter code for an architecture
379
+ * @param col the seccomp filter collection
380
+ * @param db the single seccomp filter
381
+ * @param fds the file stream to send the output
382
+ *
383
+ * This function generates a pseudo filter code representation of the given
384
+ * filter DB and writes it to the given output stream. Returns zero on
385
+ * success, negative values on failure.
386
+ *
387
+ */
388
+ static int _gen_pfc_arch(const struct db_filter_col *col,
389
+ const struct db_filter *db, FILE *fds,
390
+ uint32_t optimize)
391
+ {
392
+ int rc = 0, i = 0, lookahead_num;
393
+ unsigned int syscall_cnt = 0, bintree_levels, level, indent = 1;
394
+ struct pfc_sys_list *p_iter = NULL, *p_head = NULL;
395
+
396
+ /* sort the syscall list */
397
+ rc = _sys_sort(db->syscalls, &p_head, optimize);
398
+ if (rc < 0)
399
+ goto arch_return;
400
+
401
+ bintree_levels = _get_bintree_levels(db->syscall_cnt, optimize);
402
+
306
403
  fprintf(fds, "# filter for arch %s (%u)\n",
307
404
  _pfc_arch(db->arch), db->arch->token_bpf);
308
405
  fprintf(fds, "if ($arch == %u)\n", db->arch->token_bpf);
@@ -312,8 +409,40 @@ static int _gen_pfc_arch(const struct db_filter_col *col,
312
409
  p_iter = p_iter->next;
313
410
  continue;
314
411
  }
315
- _gen_pfc_syscall(db->arch, p_iter->sys, fds);
412
+
413
+ for (i = bintree_levels - 1; i > 0; i--) {
414
+ level = SYSCALLS_PER_NODE << i;
415
+
416
+ if (syscall_cnt == 0 || (syscall_cnt % level) == 0) {
417
+ rc = _get_bintree_syscall_num(p_iter, level / 2,
418
+ &lookahead_num);
419
+ if (rc < 0)
420
+ /* We have reached the end of the bintree.
421
+ * There aren't enough syscalls to construct
422
+ * any more if-elses.
423
+ */
424
+ continue;
425
+ _indent(fds, indent);
426
+ fprintf(fds, "if ($syscall > %u)\n", lookahead_num);
427
+ indent++;
428
+ } else if ((syscall_cnt % (level / 2)) == 0) {
429
+ lookahead_num = p_iter->sys->num;
430
+ _indent(fds, indent - 1);
431
+ fprintf(fds, "else # ($syscall <= %u)\n",
432
+ p_iter->sys->num);
433
+ }
434
+
435
+ }
436
+
437
+ _gen_pfc_syscall(db->arch, p_iter->sys, fds, indent);
438
+ syscall_cnt++;
316
439
  p_iter = p_iter->next;
440
+
441
+ /* undo the indentations as the else statements complete */
442
+ for (i = 0; i < bintree_levels; i++) {
443
+ if (syscall_cnt % ((SYSCALLS_PER_NODE * 2) << i) == 0)
444
+ indent--;
445
+ }
317
446
  }
318
447
  _indent(fds, 1);
319
448
  fprintf(fds, "# default action\n");
@@ -328,7 +457,6 @@ arch_return:
328
457
  }
329
458
  return rc;
330
459
  }
331
-
332
460
  /**
333
461
  * Generate a pseudo filter code string representation
334
462
  * @param col the seccomp filter collection
@@ -336,23 +464,22 @@ arch_return:
336
464
  *
337
465
  * This function generates a pseudo filter code representation of the given
338
466
  * filter collection and writes it to the given fd. Returns zero on success,
339
- * negative values on failure.
467
+ * negative errno values on failure.
340
468
  *
341
469
  */
342
470
  int gen_pfc_generate(const struct db_filter_col *col, int fd)
343
471
  {
344
- int rc = 0;
345
472
  int newfd;
346
473
  unsigned int iter;
347
474
  FILE *fds;
348
475
 
349
476
  newfd = dup(fd);
350
477
  if (newfd < 0)
351
- return errno;
478
+ return -errno;
352
479
  fds = fdopen(newfd, "a");
353
480
  if (fds == NULL) {
354
481
  close(newfd);
355
- return errno;
482
+ return -errno;
356
483
  }
357
484
 
358
485
  /* generate the pfc */
@@ -361,7 +488,8 @@ int gen_pfc_generate(const struct db_filter_col *col, int fd)
361
488
  fprintf(fds, "#\n");
362
489
 
363
490
  for (iter = 0; iter < col->filter_cnt; iter++)
364
- _gen_pfc_arch(col, col->filters[iter], fds);
491
+ _gen_pfc_arch(col, col->filters[iter], fds,
492
+ col->attr.optimize);
365
493
 
366
494
  fprintf(fds, "# invalid architecture action\n");
367
495
  _pfc_action(fds, col->attr.act_badarch);
@@ -372,5 +500,5 @@ int gen_pfc_generate(const struct db_filter_col *col, int fd)
372
500
  fflush(fds);
373
501
  fclose(fds);
374
502
 
375
- return rc;
503
+ return 0;
376
504
  }
@@ -19,7 +19,8 @@
19
19
  # along with this library; if not, see <http://www.gnu.org/licenses>.
20
20
  #
21
21
 
22
- from libc.stdint cimport uint8_t, uint32_t, uint64_t
22
+ from libc.stdint cimport int8_t, int16_t, int32_t, int64_t
23
+ from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t
23
24
 
24
25
  cdef extern from "seccomp.h":
25
26
 
@@ -50,6 +51,7 @@ cdef extern from "seccomp.h":
50
51
  SCMP_ARCH_PPC64LE
51
52
  SCMP_ARCH_S390
52
53
  SCMP_ARCH_S390X
54
+ SCMP_ARCH_RISCV64
53
55
 
54
56
  cdef enum scmp_filter_attr:
55
57
  SCMP_FLTATR_ACT_DEFAULT
@@ -58,6 +60,9 @@ cdef extern from "seccomp.h":
58
60
  SCMP_FLTATR_CTL_TSYNC
59
61
  SCMP_FLTATR_API_TSKIP
60
62
  SCMP_FLTATR_CTL_LOG
63
+ SCMP_FLTATR_CTL_SSB
64
+ SCMP_FLTATR_CTL_OPTIMIZE
65
+ SCMP_FLTATR_API_SYSRAWRC
61
66
 
62
67
  cdef enum scmp_compare:
63
68
  SCMP_CMP_NE
@@ -74,6 +79,7 @@ cdef extern from "seccomp.h":
74
79
  SCMP_ACT_TRAP
75
80
  SCMP_ACT_LOG
76
81
  SCMP_ACT_ALLOW
82
+ SCMP_ACT_NOTIFY
77
83
  unsigned int SCMP_ACT_ERRNO(int errno)
78
84
  unsigned int SCMP_ACT_TRACE(int value)
79
85
 
@@ -85,6 +91,29 @@ cdef extern from "seccomp.h":
85
91
  scmp_datum_t datum_a
86
92
  scmp_datum_t datum_b
87
93
 
94
+ cdef struct seccomp_data:
95
+ int nr
96
+ uint32_t arch
97
+ uint64_t instruction_pointer
98
+ uint64_t args[6]
99
+
100
+ cdef struct seccomp_notif_sizes:
101
+ uint16_t seccomp_notif
102
+ uint16_t seccomp_notif_resp
103
+ uint16_t seccomp_data
104
+
105
+ cdef struct seccomp_notif:
106
+ uint64_t id
107
+ uint32_t pid
108
+ uint32_t flags
109
+ seccomp_data data
110
+
111
+ cdef struct seccomp_notif_resp:
112
+ uint64_t id
113
+ int64_t val
114
+ int32_t error
115
+ uint32_t flags
116
+
88
117
  scmp_version *seccomp_version()
89
118
 
90
119
  unsigned int seccomp_api_get()
@@ -129,6 +158,13 @@ cdef extern from "seccomp.h":
129
158
  unsigned int arg_cnt,
130
159
  scmp_arg_cmp *arg_array)
131
160
 
161
+ int seccomp_notify_alloc(seccomp_notif **req, seccomp_notif_resp **resp)
162
+ void seccomp_notify_free(seccomp_notif *req, seccomp_notif_resp *resp)
163
+ int seccomp_notify_receive(int fd, seccomp_notif *req)
164
+ int seccomp_notify_respond(int fd, seccomp_notif_resp *resp)
165
+ int seccomp_notify_id_valid(int fd, uint64_t id)
166
+ int seccomp_notify_fd(scmp_filter_ctx ctx)
167
+
132
168
  int seccomp_export_pfc(scmp_filter_ctx ctx, int fd)
133
169
  int seccomp_export_bpf(scmp_filter_ctx ctx, int fd)
134
170
 
@@ -36,6 +36,7 @@ Filter action values:
36
36
  LOG - allow the syscall to be executed after the action has been logged
37
37
  ALLOW - allow the syscall to execute
38
38
  TRAP - a SIGSYS signal will be thrown
39
+ NOTIFY - a notification event will be sent via the notification API
39
40
  ERRNO(x) - syscall will return (x)
40
41
  TRACE(x) - if the process is being traced, (x) will be returned to the
41
42
  tracing process via PTRACE_EVENT_SECCOMP and the
@@ -60,13 +61,18 @@ Example:
60
61
  # create a filter object with a default KILL action
61
62
  f = SyscallFilter(defaction=KILL)
62
63
 
64
+ # add some basic syscalls which python typically wants
65
+ f.add_rule(ALLOW, "rt_sigaction")
66
+ f.add_rule(ALLOW, "rt_sigreturn")
67
+ f.add_rule(ALLOW, "exit_group")
68
+ f.add_rule(ALLOW, "brk")
69
+
63
70
  # add syscall filter rules to allow certain syscalls
64
71
  f.add_rule(ALLOW, "open")
65
72
  f.add_rule(ALLOW, "close")
66
- f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin))
67
- f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout))
68
- f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr))
69
- f.add_rule(ALLOW, "rt_sigreturn")
73
+ f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno()))
74
+ f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno()))
75
+ f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno()))
70
76
 
71
77
  # load the filter into the kernel
72
78
  f.load()
@@ -75,7 +81,9 @@ __author__ = 'Paul Moore <paul@paul-moore.com>'
75
81
  __date__ = "3 February 2017"
76
82
 
77
83
  from cpython.version cimport PY_MAJOR_VERSION
78
- from libc.stdint cimport uint32_t
84
+ from libc.stdint cimport int8_t, int16_t, int32_t, int64_t
85
+ from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t
86
+ from libc.stdlib cimport free
79
87
  import errno
80
88
 
81
89
  cimport libseccomp
@@ -102,6 +110,7 @@ KILL = libseccomp.SCMP_ACT_KILL
102
110
  TRAP = libseccomp.SCMP_ACT_TRAP
103
111
  LOG = libseccomp.SCMP_ACT_LOG
104
112
  ALLOW = libseccomp.SCMP_ACT_ALLOW
113
+ NOTIFY = libseccomp.SCMP_ACT_NOTIFY
105
114
  def ERRNO(int errno):
106
115
  """The action ERRNO(x) means that the syscall will return (x).
107
116
  To conform to Linux syscall calling conventions, the syscall return
@@ -205,6 +214,7 @@ cdef class Arch:
205
214
  PARISC64 - 64-bit PA-RISC
206
215
  PPC64 - 64-bit PowerPC
207
216
  PPC - 32-bit PowerPC
217
+ RISCV64 - 64-bit RISC-V
208
218
  """
209
219
 
210
220
  cdef int _token
@@ -228,6 +238,7 @@ cdef class Arch:
228
238
  PPC64LE = libseccomp.SCMP_ARCH_PPC64LE
229
239
  S390 = libseccomp.SCMP_ARCH_S390
230
240
  S390X = libseccomp.SCMP_ARCH_S390X
241
+ RISCV64 = libseccomp.SCMP_ARCH_RISCV64
231
242
 
232
243
  def __cinit__(self, arch=libseccomp.SCMP_ARCH_NATIVE):
233
244
  """ Initialize the architecture object.
@@ -303,6 +314,15 @@ cdef class Attr:
303
314
  ACT_BADARCH - the filter's bad architecture action
304
315
  CTL_NNP - the filter's "no new privileges" flag
305
316
  CTL_NNP - the filter's thread sync flag
317
+ CTL_TSYNC - sync threads on filter load
318
+ CTL_TSKIP - allow rules with a -1 syscall number
319
+ CTL_LOG - log not-allowed actions
320
+ CTL_SSB - disable SSB mitigations
321
+ CTL_OPTIMIZE - the filter's optimization level:
322
+ 0: currently unused
323
+ 1: rules weighted by priority and complexity (DEFAULT)
324
+ 2: binary tree sorted by syscall number
325
+ API_SYSRAWRC - return the raw syscall codes
306
326
  """
307
327
  ACT_DEFAULT = libseccomp.SCMP_FLTATR_ACT_DEFAULT
308
328
  ACT_BADARCH = libseccomp.SCMP_FLTATR_ACT_BADARCH
@@ -310,6 +330,9 @@ cdef class Attr:
310
330
  CTL_TSYNC = libseccomp.SCMP_FLTATR_CTL_TSYNC
311
331
  API_TSKIP = libseccomp.SCMP_FLTATR_API_TSKIP
312
332
  CTL_LOG = libseccomp.SCMP_FLTATR_CTL_LOG
333
+ CTL_SSB = libseccomp.SCMP_FLTATR_CTL_SSB
334
+ CTL_OPTIMIZE = libseccomp.SCMP_FLTATR_CTL_OPTIMIZE
335
+ API_SYSRAWRC = libseccomp.SCMP_FLTATR_API_SYSRAWRC
313
336
 
314
337
  cdef class Arg:
315
338
  """ Python object representing a SyscallFilter syscall argument.
@@ -344,6 +367,218 @@ cdef class Arg:
344
367
  """
345
368
  return self._arg
346
369
 
370
+ cdef class Notification:
371
+ """ Python object representing a seccomp notification.
372
+ """
373
+ cdef uint64_t _id
374
+ cdef uint32_t _pid
375
+ cdef uint32_t _flags
376
+ cdef int _syscall
377
+ cdef uint32_t _syscall_arch
378
+ cdef uint64_t _syscall_ip
379
+ cdef uint64_t _syscall_args[6]
380
+
381
+ def __cinit__(self, id, pid, flags, syscall, arch, ip, args):
382
+ """ Initialize the notification.
383
+
384
+ Arguments:
385
+ id - the notification ID
386
+ pid - the process ID
387
+ flags - the notification flags
388
+ syscall - the syscall number
389
+ ip - the instruction pointer
390
+ args - list of the six syscall arguments
391
+
392
+ Description:
393
+ Create a seccomp Notification object.
394
+ """
395
+ self._id = id
396
+ self._pid = pid
397
+ self._flags = flags
398
+ self._syscall = syscall
399
+ self._syscall_arch = arch
400
+ self._syscall_ip = ip
401
+ self._syscall_args[0] = args[0]
402
+ self._syscall_args[1] = args[1]
403
+ self._syscall_args[2] = args[2]
404
+ self._syscall_args[3] = args[3]
405
+ self._syscall_args[4] = args[4]
406
+ self._syscall_args[5] = args[5]
407
+
408
+ @property
409
+ def id(self):
410
+ """ Get the seccomp notification ID.
411
+
412
+ Description:
413
+ Get the seccomp notification ID.
414
+ """
415
+ return self._id
416
+
417
+ @property
418
+ def pid(self):
419
+ """ Get the seccomp notification process ID.
420
+
421
+ Description:
422
+ Get the seccomp notification process ID.
423
+ """
424
+ return self._pid
425
+
426
+ @property
427
+ def flags(self):
428
+ """ Get the seccomp notification flags.
429
+
430
+ Description:
431
+ Get the seccomp notification flags.
432
+ """
433
+ return self._flags
434
+
435
+ @property
436
+ def syscall(self):
437
+ """ Get the seccomp notification syscall.
438
+
439
+ Description:
440
+ Get the seccomp notification syscall.
441
+ """
442
+ return self._syscall
443
+
444
+ @property
445
+ def syscall_arch(self):
446
+ """ Get the seccomp notification syscall architecture.
447
+
448
+ Description:
449
+ Get the seccomp notification syscall architecture.
450
+ """
451
+ return self._syscall_arch
452
+
453
+ @property
454
+ def syscall_ip(self):
455
+ """ Get the seccomp notification syscall instruction pointer.
456
+
457
+ Description:
458
+ Get the seccomp notification syscall instruction pointer.
459
+ """
460
+ return self._syscall_ip
461
+
462
+ @property
463
+ def syscall_args(self):
464
+ """ Get the seccomp notification syscall arguments.
465
+
466
+ Description:
467
+ Get the seccomp notification syscall arguments in a six element list.
468
+ """
469
+ return [self._syscall_args[0], self._syscall_args[1],
470
+ self._syscall_args[2], self._syscall_args[3],
471
+ self._syscall_args[4], self._syscall_args[5]]
472
+
473
+ cdef class NotificationResponse:
474
+ """ Python object representing a seccomp notification response.
475
+ """
476
+ cdef uint64_t _id
477
+ cdef int64_t _val
478
+ cdef int32_t _error
479
+ cdef uint32_t _flags
480
+
481
+ def __cinit__(self, notify, val = 0, error = 0, flags = 0):
482
+ """ Initialize the notification response.
483
+
484
+ Arguments:
485
+ notify - a Notification object
486
+ val - the notification response value
487
+ error - the notification response error
488
+ flags - the notification response flags
489
+
490
+ Description:
491
+ Create a seccomp NotificationResponse object.
492
+ """
493
+ self._id = notify.id
494
+ self._val = val
495
+ self._error = error
496
+ self._flags = flags
497
+
498
+ @property
499
+ def id(self):
500
+ """ Get the seccomp notification response ID.
501
+
502
+ Description:
503
+ Get the seccomp notification response ID.
504
+ """
505
+ return self._id
506
+
507
+ @id.setter
508
+ def id(self, value):
509
+ """ Set the seccomp notification response ID.
510
+
511
+ Arguments:
512
+ id - the notification response ID
513
+
514
+ Description:
515
+ Set the seccomp notification response ID.
516
+ """
517
+ self._id = value
518
+
519
+ @property
520
+ def val(self):
521
+ """ Get the seccomp notification response value.
522
+
523
+ Description:
524
+ Get the seccomp notification response value.
525
+ """
526
+ return self._val
527
+
528
+ @val.setter
529
+ def val(self, value):
530
+ """ Set the seccomp notification response value.
531
+
532
+ Arguments:
533
+ val - the notification response value
534
+
535
+ Description:
536
+ Set the seccomp notification response value.
537
+ """
538
+ self._val = value
539
+
540
+ @property
541
+ def error(self):
542
+ """ Get the seccomp notification response error.
543
+
544
+ Description:
545
+ Get the seccomp notification response error.
546
+ """
547
+ return self._error
548
+
549
+ @error.setter
550
+ def error(self, value):
551
+ """ Set the seccomp notification response error.
552
+
553
+ Arguments:
554
+ error - the notification response error
555
+
556
+ Description:
557
+ Set the seccomp notification response error.
558
+ """
559
+ self._error = value
560
+
561
+ @property
562
+ def flags(self):
563
+ """ Get the seccomp notification response flags.
564
+
565
+ Description:
566
+ Get the seccomp notification response flags.
567
+ """
568
+ return self._flags
569
+
570
+ @flags.setter
571
+ def flags(self, value):
572
+ """ Set the seccomp notification response flags.
573
+
574
+ Arguments:
575
+ flags - the notification response flags
576
+
577
+ Description:
578
+ Set the seccomp notification response flags.
579
+ """
580
+ self._flags = value
581
+
347
582
  cdef class SyscallFilter:
348
583
  """ Python object representing a seccomp syscall filter. """
349
584
  cdef int _defaction
@@ -712,6 +947,60 @@ cdef class SyscallFilter:
712
947
  if rc != 0:
713
948
  raise RuntimeError(str.format("Library error (errno = {0})", rc))
714
949
 
950
+ def receive_notify(self):
951
+ """ Receive seccomp notifications.
952
+
953
+ Description:
954
+ Receive a seccomp notification from the system, requires the use of
955
+ the NOTIFY action.
956
+ """
957
+ cdef libseccomp.seccomp_notif *req
958
+
959
+ fd = libseccomp.seccomp_notify_fd(self._ctx)
960
+ if fd < 0:
961
+ raise RuntimeError("Notifications not enabled/active")
962
+ rc = libseccomp.seccomp_notify_alloc(&req, NULL)
963
+ if rc < 0:
964
+ raise RuntimeError(str.format("Library error (errno = {0})", rc))
965
+ rc = libseccomp.seccomp_notify_receive(fd, req)
966
+ if rc < 0:
967
+ raise RuntimeError(str.format("Library error (errno = {0})", rc))
968
+ rc = libseccomp.seccomp_notify_id_valid(fd, req.id)
969
+ if rc < 0:
970
+ raise RuntimeError(str.format("Library error (errno = {0})", rc))
971
+ notify = Notification(req.id, req.pid, req.flags, req.data.nr,
972
+ req.data.arch, req.data.instruction_pointer,
973
+ [req.data.args[0], req.data.args[1],
974
+ req.data.args[2], req.data.args[3],
975
+ req.data.args[4], req.data.args[5]])
976
+ free(req)
977
+ return notify
978
+
979
+ def respond_notify(self, response):
980
+ """ Send a seccomp notification response.
981
+
982
+ Arguments:
983
+ response - the response to send to the system
984
+
985
+ Description:
986
+ Respond to a seccomp notification.
987
+ """
988
+ cdef libseccomp.seccomp_notif_resp *resp
989
+
990
+ fd = libseccomp.seccomp_notify_fd(self._ctx)
991
+ if fd < 0:
992
+ raise RuntimeError("Notifications not enabled/active")
993
+ rc = libseccomp.seccomp_notify_alloc(NULL, &resp)
994
+ if rc < 0:
995
+ raise RuntimeError(str.format("Library error (errno = {0})", rc))
996
+ resp.id = response.id
997
+ resp.val = response.val
998
+ resp.error = response.error
999
+ resp.flags = response.flags
1000
+ rc = libseccomp.seccomp_notify_respond(fd, resp)
1001
+ if rc < 0:
1002
+ raise RuntimeError(str.format("Library error (errno = {0})", rc))
1003
+
715
1004
  def export_pfc(self, file):
716
1005
  """ Export the filter in PFC format.
717
1006
 
@@ -733,6 +1022,7 @@ cdef class SyscallFilter:
733
1022
  Arguments:
734
1023
  file - the output file
735
1024
 
1025
+ Description:
736
1026
  Output the filter in Berkley Packet Filter (BPF) to the given
737
1027
  file. The output is identical to what is loaded into the
738
1028
  Linux Kernel.