]> git.proxmox.com Git - mirror_libseccomp.git/blob - src/python/seccomp.pyx
api: rename SCMP_FLTATR_SPEC_ALLOW to SCMP_FLTATR_CTL_SSB
[mirror_libseccomp.git] / src / python / seccomp.pyx
1 #
2 # Seccomp Library Python Bindings
3 #
4 # Copyright (c) 2012,2013,2017 Red Hat <pmoore@redhat.com>
5 # Author: Paul Moore <paul@paul-moore.com>
6 #
7
8 #
9 # This library is free software; you can redistribute it and/or modify it
10 # under the terms of version 2.1 of the GNU Lesser General Public License as
11 # published by the Free Software Foundation.
12 #
13 # This library is distributed in the hope that it will be useful, but WITHOUT
14 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 # for more details.
17 #
18 # You should have received a copy of the GNU Lesser General Public License
19 # along with this library; if not, see <http://www.gnu.org/licenses>.
20 #
21
22 """ Python bindings for the libseccomp library
23
24 The libseccomp library provides and easy to use, platform independent,
25 interface to the Linux Kernel's syscall filtering mechanism: seccomp. The
26 libseccomp API is designed to abstract away the underlying BPF based
27 syscall filter language and present a more conventional function-call
28 based filtering interface that should be familiar to, and easily adopted
29 by application developers.
30
31 Filter action values:
32 KILL_PROCESS - kill the process
33 KILL - kill the thread
34 LOG - allow the syscall to be executed after the action has been logged
35 ALLOW - allow the syscall to execute
36 TRAP - a SIGSYS signal will be thrown
37 ERRNO(x) - syscall will return (x)
38 TRACE(x) - if the process is being traced, (x) will be returned to the
39 tracing process via PTRACE_EVENT_SECCOMP and the
40 PTRACE_GETEVENTMSG option
41
42 Argument comparison values (see the Arg class):
43
44 NE - arg != datum_a
45 LT - arg < datum_a
46 LE - arg <= datum_a
47 EQ - arg == datum_a
48 GT - arg > datum_a
49 GE - arg >= datum_a
50 MASKED_EQ - (arg & datum_a) == datum_b
51
52
53 Example:
54
55 import sys
56 from seccomp import *
57
58 # create a filter object with a default KILL action
59 f = SyscallFilter(defaction=KILL)
60
61 # add syscall filter rules to allow certain syscalls
62 f.add_rule(ALLOW, "open")
63 f.add_rule(ALLOW, "close")
64 f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin))
65 f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout))
66 f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr))
67 f.add_rule(ALLOW, "rt_sigreturn")
68
69 # load the filter into the kernel
70 f.load()
71 """
72 __author__ = 'Paul Moore <paul@paul-moore.com>'
73 __date__ = "3 February 2017"
74
75 from cpython.version cimport PY_MAJOR_VERSION
76 from libc.stdint cimport uint32_t
77 import errno
78
79 cimport libseccomp
80
81 def c_str(string):
82 """ Convert a Python string to a C string.
83
84 Arguments:
85 string - the Python string
86
87 Description:
88 Convert the Python string into a form usable by C taking into consideration
89 the Python major version, e.g. Python 2.x or Python 3.x.
90 See http://docs.cython.org/en/latest/src/tutorial/strings.html for more
91 information.
92 """
93 if PY_MAJOR_VERSION < 3:
94 return string
95 else:
96 return bytes(string, "ascii")
97
98 KILL_PROCESS = libseccomp.SCMP_ACT_KILL_PROCESS
99 KILL = libseccomp.SCMP_ACT_KILL
100 TRAP = libseccomp.SCMP_ACT_TRAP
101 LOG = libseccomp.SCMP_ACT_LOG
102 ALLOW = libseccomp.SCMP_ACT_ALLOW
103 def ERRNO(int errno):
104 """The action ERRNO(x) means that the syscall will return (x).
105 To conform to Linux syscall calling conventions, the syscall return
106 value should almost always be a negative number.
107 """
108 return libseccomp.SCMP_ACT_ERRNO(errno)
109 def TRACE(int value):
110 """The action TRACE(x) means that, if the process is being traced, (x)
111 will be returned to the tracing process via PTRACE_EVENT_SECCOMP
112 and the PTRACE_GETEVENTMSG option.
113 """
114 return libseccomp.SCMP_ACT_TRACE(value)
115
116 NE = libseccomp.SCMP_CMP_NE
117 LT = libseccomp.SCMP_CMP_LT
118 LE = libseccomp.SCMP_CMP_LE
119 EQ = libseccomp.SCMP_CMP_EQ
120 GE = libseccomp.SCMP_CMP_GE
121 GT = libseccomp.SCMP_CMP_GT
122 MASKED_EQ = libseccomp.SCMP_CMP_MASKED_EQ
123
124 def system_arch():
125 """ Return the system architecture value.
126
127 Description:
128 Returns the native system architecture value.
129 """
130 return libseccomp.seccomp_arch_native()
131
132 def resolve_syscall(arch, syscall):
133 """ Resolve the syscall.
134
135 Arguments:
136 arch - the architecture value, e.g. Arch.*
137 syscall - the syscall name or number
138
139 Description:
140 Resolve an architecture's syscall name to the correct number or the
141 syscall number to the correct name.
142 """
143 cdef char *ret_str
144
145 if isinstance(syscall, basestring):
146 return libseccomp.seccomp_syscall_resolve_name_rewrite(arch,
147 c_str(syscall))
148 elif isinstance(syscall, int):
149 ret_str = libseccomp.seccomp_syscall_resolve_num_arch(arch, syscall)
150 if ret_str is NULL:
151 raise ValueError('Unknown syscall %d on arch %d' % (syscall, arch))
152 else:
153 return ret_str
154 else:
155 raise TypeError("Syscall must either be an int or str type")
156
157 def get_api():
158 """ Query the level of API support
159
160 Description:
161 Returns the API level value indicating the current supported
162 functionality.
163 """
164 level = libseccomp.seccomp_api_get()
165 if level < 0:
166 raise RuntimeError(str.format("Library error (errno = {0})", level))
167
168 return level
169
170 def set_api(unsigned int level):
171 """ Set the level of API support
172
173 Arguments:
174 level - the API level
175
176 Description:
177 This function forcibly sets the API level at runtime. General use
178 of this function is strongly discouraged.
179 """
180 rc = libseccomp.seccomp_api_set(level)
181 if rc == -errno.EINVAL:
182 raise ValueError("Invalid level")
183 elif rc != 0:
184 raise RuntimeError(str.format("Library error (errno = {0})", rc))
185
186 cdef class Arch:
187 """ Python object representing the SyscallFilter architecture values.
188
189 Data values:
190 NATIVE - the native architecture
191 X86 - 32-bit x86
192 X86_64 - 64-bit x86
193 X32 - 64-bit x86 using the x32 ABI
194 ARM - ARM
195 AARCH64 - 64-bit ARM
196 MIPS - MIPS O32 ABI
197 MIPS64 - MIPS 64-bit ABI
198 MIPS64N32 - MIPS N32 ABI
199 MIPSEL - MIPS little endian O32 ABI
200 MIPSEL64 - MIPS little endian 64-bit ABI
201 MIPSEL64N32 - MIPS little endian N32 ABI
202 PARISC - 32-bit PA-RISC
203 PARISC64 - 64-bit PA-RISC
204 PPC64 - 64-bit PowerPC
205 PPC - 32-bit PowerPC
206 """
207
208 cdef int _token
209
210 NATIVE = libseccomp.SCMP_ARCH_NATIVE
211 X86 = libseccomp.SCMP_ARCH_X86
212 X86_64 = libseccomp.SCMP_ARCH_X86_64
213 X32 = libseccomp.SCMP_ARCH_X32
214 ARM = libseccomp.SCMP_ARCH_ARM
215 AARCH64 = libseccomp.SCMP_ARCH_AARCH64
216 MIPS = libseccomp.SCMP_ARCH_MIPS
217 MIPS64 = libseccomp.SCMP_ARCH_MIPS64
218 MIPS64N32 = libseccomp.SCMP_ARCH_MIPS64N32
219 MIPSEL = libseccomp.SCMP_ARCH_MIPSEL
220 MIPSEL64 = libseccomp.SCMP_ARCH_MIPSEL64
221 MIPSEL64N32 = libseccomp.SCMP_ARCH_MIPSEL64N32
222 PARISC = libseccomp.SCMP_ARCH_PARISC
223 PARISC64 = libseccomp.SCMP_ARCH_PARISC64
224 PPC = libseccomp.SCMP_ARCH_PPC
225 PPC64 = libseccomp.SCMP_ARCH_PPC64
226 PPC64LE = libseccomp.SCMP_ARCH_PPC64LE
227 S390 = libseccomp.SCMP_ARCH_S390
228 S390X = libseccomp.SCMP_ARCH_S390X
229
230 def __cinit__(self, arch=libseccomp.SCMP_ARCH_NATIVE):
231 """ Initialize the architecture object.
232
233 Arguments:
234 arch - the architecture name or token value
235
236 Description:
237 Create an architecture object using the given name or token value.
238 """
239 if isinstance(arch, int):
240 if arch == libseccomp.SCMP_ARCH_NATIVE:
241 self._token = libseccomp.seccomp_arch_native()
242 elif arch == libseccomp.SCMP_ARCH_X86:
243 self._token = libseccomp.SCMP_ARCH_X86
244 elif arch == libseccomp.SCMP_ARCH_X86_64:
245 self._token = libseccomp.SCMP_ARCH_X86_64
246 elif arch == libseccomp.SCMP_ARCH_X32:
247 self._token = libseccomp.SCMP_ARCH_X32
248 elif arch == libseccomp.SCMP_ARCH_ARM:
249 self._token = libseccomp.SCMP_ARCH_ARM
250 elif arch == libseccomp.SCMP_ARCH_AARCH64:
251 self._token = libseccomp.SCMP_ARCH_AARCH64
252 elif arch == libseccomp.SCMP_ARCH_MIPS:
253 self._token = libseccomp.SCMP_ARCH_MIPS
254 elif arch == libseccomp.SCMP_ARCH_MIPS64:
255 self._token = libseccomp.SCMP_ARCH_MIPS64
256 elif arch == libseccomp.SCMP_ARCH_MIPS64N32:
257 self._token = libseccomp.SCMP_ARCH_MIPS64N32
258 elif arch == libseccomp.SCMP_ARCH_MIPSEL:
259 self._token = libseccomp.SCMP_ARCH_MIPSEL
260 elif arch == libseccomp.SCMP_ARCH_MIPSEL64:
261 self._token = libseccomp.SCMP_ARCH_MIPSEL64
262 elif arch == libseccomp.SCMP_ARCH_MIPSEL64N32:
263 self._token = libseccomp.SCMP_ARCH_MIPSEL64N32
264 elif arch == libseccomp.SCMP_ARCH_PARISC:
265 self._token = libseccomp.SCMP_ARCH_PARISC
266 elif arch == libseccomp.SCMP_ARCH_PARISC64:
267 self._token = libseccomp.SCMP_ARCH_PARISC64
268 elif arch == libseccomp.SCMP_ARCH_PPC:
269 self._token = libseccomp.SCMP_ARCH_PPC
270 elif arch == libseccomp.SCMP_ARCH_PPC64:
271 self._token = libseccomp.SCMP_ARCH_PPC64
272 elif arch == libseccomp.SCMP_ARCH_PPC64LE:
273 self._token = libseccomp.SCMP_ARCH_PPC64LE
274 elif arch == libseccomp.SCMP_ARCH_S390:
275 self._token = libseccomp.SCMP_ARCH_S390
276 elif arch == libseccomp.SCMP_ARCH_S390X:
277 self._token = libseccomp.SCMP_ARCH_S390X
278 else:
279 self._token = 0;
280 elif isinstance(arch, basestring):
281 self._token = libseccomp.seccomp_arch_resolve_name(c_str(arch))
282 else:
283 raise TypeError("Architecture must be an int or str type")
284 if self._token == 0:
285 raise ValueError("Invalid architecture")
286
287 def __int__(self):
288 """ Convert the architecture object to a token value.
289
290 Description:
291 Convert the architecture object to an integer representing the
292 architecture's token value.
293 """
294 return self._token
295
296 cdef class Attr:
297 """ Python object representing the SyscallFilter attributes.
298
299 Data values:
300 ACT_DEFAULT - the filter's default action
301 ACT_BADARCH - the filter's bad architecture action
302 CTL_NNP - the filter's "no new privileges" flag
303 CTL_NNP - the filter's thread sync flag
304 """
305 ACT_DEFAULT = libseccomp.SCMP_FLTATR_ACT_DEFAULT
306 ACT_BADARCH = libseccomp.SCMP_FLTATR_ACT_BADARCH
307 CTL_NNP = libseccomp.SCMP_FLTATR_CTL_NNP
308 CTL_TSYNC = libseccomp.SCMP_FLTATR_CTL_TSYNC
309 API_TSKIP = libseccomp.SCMP_FLTATR_API_TSKIP
310 CTL_LOG = libseccomp.SCMP_FLTATR_CTL_LOG
311 CTL_SSB = libseccomp.SCMP_FLTATR_CTL_SSB
312
313 cdef class Arg:
314 """ Python object representing a SyscallFilter syscall argument.
315 """
316 cdef libseccomp.scmp_arg_cmp _arg
317
318 def __cinit__(self, arg, op, datum_a, datum_b = 0):
319 """ Initialize the argument comparison.
320
321 Arguments:
322 arg - the argument number, starting at 0
323 op - the argument comparison operator, e.g. {NE,LT,LE,...}
324 datum_a - argument value
325 datum_b - argument value, only valid when op == MASKED_EQ
326
327 Description:
328 Create an argument comparison object for use with SyscallFilter.
329 """
330 self._arg.arg = arg
331 self._arg.op = op
332 self._arg.datum_a = datum_a
333 self._arg.datum_b = datum_b
334
335 cdef libseccomp.scmp_arg_cmp to_c(self):
336 """ Convert the object into a C structure.
337
338 Description:
339 Helper function which should only be used internally by
340 SyscallFilter objects and exists for the sole purpose of making it
341 easier to deal with the varadic functions of the libseccomp API,
342 e.g. seccomp_rule_add().
343 """
344 return self._arg
345
346 cdef class SyscallFilter:
347 """ Python object representing a seccomp syscall filter. """
348 cdef int _defaction
349 cdef libseccomp.scmp_filter_ctx _ctx
350
351 def __cinit__(self, int defaction):
352 self._ctx = libseccomp.seccomp_init(defaction)
353 if self._ctx == NULL:
354 raise RuntimeError("Library error")
355 _defaction = defaction
356
357 def __init__(self, defaction):
358 """ Initialize the filter state
359
360 Arguments:
361 defaction - the default filter action
362
363 Description:
364 Initializes the seccomp filter state to the defaults.
365 """
366
367 def __dealloc__(self):
368 """ Destroys the filter state and releases any resources.
369
370 Description:
371 Destroys the seccomp filter state and releases any resources
372 associated with the filter state. This function does not affect
373 any seccomp filters already loaded into the kernel.
374 """
375 if self._ctx != NULL:
376 libseccomp.seccomp_release(self._ctx)
377
378 def reset(self, int defaction = -1):
379 """ Reset the filter state.
380
381 Arguments:
382 defaction - the default filter action
383
384 Description:
385 Resets the seccomp filter state to an initial default state, if a
386 default filter action is not specified in the reset call the
387 original action will be reused. This function does not affect any
388 seccomp filters alread loaded into the kernel.
389 """
390 if defaction == -1:
391 defaction = self._defaction
392 rc = libseccomp.seccomp_reset(self._ctx, defaction)
393 if rc == -errno.EINVAL:
394 raise ValueError("Invalid action")
395 if rc != 0:
396 raise RuntimeError(str.format("Library error (errno = {0})", rc))
397 _defaction = defaction
398
399 def merge(self, SyscallFilter filter):
400 """ Merge two existing SyscallFilter objects.
401
402 Arguments:
403 filter - a valid SyscallFilter object
404
405 Description:
406 Merges a valid SyscallFilter object with the current SyscallFilter
407 object; the passed filter object will be reset on success. In
408 order to successfully merge two seccomp filters they must have the
409 same attribute values and not share any of the same architectures.
410 """
411 rc = libseccomp.seccomp_merge(self._ctx, filter._ctx)
412 if rc != 0:
413 raise RuntimeError(str.format("Library error (errno = {0})", rc))
414 filter._ctx = NULL
415 filter = SyscallFilter(filter._defaction)
416
417 def exist_arch(self, arch):
418 """ Check if the seccomp filter contains a given architecture.
419
420 Arguments:
421 arch - the architecture value, e.g. Arch.*
422
423 Description:
424 Test to see if a given architecture is included in the filter.
425 Return True is the architecture exists, False if it does not
426 exist.
427 """
428 rc = libseccomp.seccomp_arch_exist(self._ctx, arch)
429 if rc == 0:
430 return True
431 elif rc == -errno.EEXIST:
432 return False
433 elif rc == -errno.EINVAL:
434 raise ValueError("Invalid architecture")
435 else:
436 raise RuntimeError(str.format("Library error (errno = {0})", rc))
437
438 def add_arch(self, arch):
439 """ Add an architecture to the filter.
440
441 Arguments:
442 arch - the architecture value, e.g. Arch.*
443
444 Description:
445 Add the given architecture to the filter. Any new rules added
446 after this method returns successfully will be added to this new
447 architecture, but any existing rules will not be added to the new
448 architecture.
449 """
450 rc = libseccomp.seccomp_arch_add(self._ctx, arch)
451 if rc == -errno.EINVAL:
452 raise ValueError("Invalid architecture")
453 elif rc != 0:
454 raise RuntimeError(str.format("Library error (errno = {0})", rc))
455
456 def remove_arch(self, arch):
457 """ Remove an architecture from the filter.
458
459 Arguments:
460 arch - the architecture value, e.g. Arch.*
461
462 Description:
463 Remove the given architecture from the filter. The filter must
464 always contain at least one architecture, so if only one
465 architecture exists in the filter this method will fail.
466 """
467 rc = libseccomp.seccomp_arch_remove(self._ctx, arch)
468 if rc == -errno.EINVAL:
469 raise ValueError("Invalid architecture")
470 elif rc != 0:
471 raise RuntimeError(str.format("Library error (errno = {0})", rc))
472
473 def load(self):
474 """ Load the filter into the Linux Kernel.
475
476 Description:
477 Load the current filter into the Linux Kernel. As soon as the
478 method returns the filter will be active and enforcing.
479 """
480 rc = libseccomp.seccomp_load(self._ctx)
481 if rc != 0:
482 raise RuntimeError(str.format("Library error (errno = {0})", rc))
483
484 def get_attr(self, attr):
485 """ Get an attribute value from the filter.
486
487 Arguments:
488 attr - the attribute, e.g. Attr.*
489
490 Description:
491 Lookup the given attribute in the filter and return the
492 attribute's value to the caller.
493 """
494 cdef uint32_t value = 0
495 rc = libseccomp.seccomp_attr_get(self._ctx,
496 attr, <uint32_t *>&value)
497 if rc == -errno.EINVAL:
498 raise ValueError("Invalid attribute")
499 elif rc != 0:
500 raise RuntimeError(str.format("Library error (errno = {0})", rc))
501 return value
502
503 def set_attr(self, attr, int value):
504 """ Set a filter attribute.
505
506 Arguments:
507 attr - the attribute, e.g. Attr.*
508 value - the attribute value
509
510 Description:
511 Lookup the given attribute in the filter and assign it the given
512 value.
513 """
514 rc = libseccomp.seccomp_attr_set(self._ctx, attr, value)
515 if rc == -errno.EINVAL:
516 raise ValueError("Invalid attribute")
517 elif rc != 0:
518 raise RuntimeError(str.format("Library error (errno = {0})", rc))
519
520 def syscall_priority(self, syscall, int priority):
521 """ Set the filter priority of a syscall.
522
523 Arguments:
524 syscall - the syscall name or number
525 priority - the priority of the syscall
526
527 Description:
528 Set the filter priority of the given syscall. A syscall with a
529 higher priority will have less overhead in the generated filter
530 code which is loaded into the system. Priority values can range
531 from 0 to 255 inclusive.
532 """
533 if priority < 0 or priority > 255:
534 raise ValueError("Syscall priority must be between 0 and 255")
535 if isinstance(syscall, str):
536 syscall_str = syscall.encode()
537 syscall_num = libseccomp.seccomp_syscall_resolve_name(syscall_str)
538 elif isinstance(syscall, int):
539 syscall_num = syscall
540 else:
541 raise TypeError("Syscall must either be an int or str type")
542 rc = libseccomp.seccomp_syscall_priority(self._ctx,
543 syscall_num, priority)
544 if rc != 0:
545 raise RuntimeError(str.format("Library error (errno = {0})", rc))
546
547 def add_rule(self, int action, syscall, *args):
548 """ Add a new rule to filter.
549
550 Arguments:
551 action - the rule action: KILL_PROCESS, KILL, TRAP, ERRNO(), TRACE(),
552 LOG, or ALLOW
553 syscall - the syscall name or number
554 args - variable number of Arg objects
555
556 Description:
557 Add a new rule to the filter, matching on the given syscall and an
558 optional list of argument comparisons. If the rule is triggered
559 the given action will be taken by the kernel. In order for the
560 rule to trigger, the syscall as well as each argument comparison
561 must be true.
562
563 In the case where the specific rule is not valid on a specific
564 architecture, e.g. socket() on 32-bit x86, this method rewrites
565 the rule to the best possible match. If you don't want this fule
566 rewriting to take place use add_rule_exactly().
567 """
568 cdef libseccomp.scmp_arg_cmp c_arg[6]
569 if isinstance(syscall, str):
570 syscall_str = syscall.encode()
571 syscall_num = libseccomp.seccomp_syscall_resolve_name(syscall_str)
572 elif isinstance(syscall, int):
573 syscall_num = syscall
574 else:
575 raise TypeError("Syscall must either be an int or str type")
576 """ NOTE: the code below exists solely to deal with the varadic
577 nature of seccomp_rule_add() function and the inability of Cython
578 to handle this automatically """
579 if len(args) > 6:
580 raise RuntimeError("Maximum number of arguments exceeded")
581 cdef Arg arg
582 for i, arg in enumerate(args):
583 c_arg[i] = arg.to_c()
584 if len(args) == 0:
585 rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num, 0)
586 elif len(args) == 1:
587 rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num,
588 len(args),
589 c_arg[0])
590 elif len(args) == 2:
591 rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num,
592 len(args),
593 c_arg[0],
594 c_arg[1])
595 elif len(args) == 3:
596 rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num,
597 len(args),
598 c_arg[0],
599 c_arg[1],
600 c_arg[2])
601 elif len(args) == 4:
602 rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num,
603 len(args),
604 c_arg[0],
605 c_arg[1],
606 c_arg[2],
607 c_arg[3])
608 elif len(args) == 5:
609 rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num,
610 len(args),
611 c_arg[0],
612 c_arg[1],
613 c_arg[2],
614 c_arg[3],
615 c_arg[4])
616 elif len(args) == 6:
617 rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num,
618 len(args),
619 c_arg[0],
620 c_arg[1],
621 c_arg[2],
622 c_arg[3],
623 c_arg[4],
624 c_arg[5])
625 else:
626 raise RuntimeError("Maximum number of arguments exceeded")
627 if rc != 0:
628 raise RuntimeError(str.format("Library error (errno = {0})", rc))
629
630 def add_rule_exactly(self, int action, syscall, *args):
631 """ Add a new rule to filter.
632
633 Arguments:
634 action - the rule action: KILL_PROCESS, KILL, TRAP, ERRNO(), TRACE(),
635 LOG, or ALLOW
636 syscall - the syscall name or number
637 args - variable number of Arg objects
638
639 Description:
640 Add a new rule to the filter, matching on the given syscall and an
641 optional list of argument comparisons. If the rule is triggered
642 the given action will be taken by the kernel. In order for the
643 rule to trigger, the syscall as well as each argument comparison
644 must be true.
645
646 This method attempts to add the filter rule exactly as specified
647 which can cause problems on certain architectures, e.g. socket()
648 on 32-bit x86. For a architecture independent version of this
649 method use add_rule().
650 """
651 cdef libseccomp.scmp_arg_cmp c_arg[6]
652 if isinstance(syscall, str):
653 syscall_str = syscall.encode()
654 syscall_num = libseccomp.seccomp_syscall_resolve_name(syscall_str)
655 elif isinstance(syscall, int):
656 syscall_num = syscall
657 else:
658 raise TypeError("Syscall must either be an int or str type")
659 """ NOTE: the code below exists solely to deal with the varadic
660 nature of seccomp_rule_add_exact() function and the inability of
661 Cython to handle this automatically """
662 if len(args) > 6:
663 raise RuntimeError("Maximum number of arguments exceeded")
664 cdef Arg arg
665 for i, arg in enumerate(args):
666 c_arg[i] = arg.to_c()
667 if len(args) == 0:
668 rc = libseccomp.seccomp_rule_add_exact(self._ctx, action,
669 syscall_num, 0)
670 elif len(args) == 1:
671 rc = libseccomp.seccomp_rule_add_exact(self._ctx, action,
672 syscall_num, len(args),
673 c_arg[0])
674 elif len(args) == 2:
675 rc = libseccomp.seccomp_rule_add_exact(self._ctx, action,
676 syscall_num, len(args),
677 c_arg[0],
678 c_arg[1])
679 elif len(args) == 3:
680 rc = libseccomp.seccomp_rule_add_exact(self._ctx, action,
681 syscall_num, len(args),
682 c_arg[0],
683 c_arg[1],
684 c_arg[2])
685 elif len(args) == 4:
686 rc = libseccomp.seccomp_rule_add_exact(self._ctx, action,
687 syscall_num, len(args),
688 c_arg[0],
689 c_arg[1],
690 c_arg[2],
691 c_arg[3])
692 elif len(args) == 5:
693 rc = libseccomp.seccomp_rule_add_exact(self._ctx, action,
694 syscall_num, len(args),
695 c_arg[0],
696 c_arg[1],
697 c_arg[2],
698 c_arg[3],
699 c_arg[4])
700 elif len(args) == 6:
701 rc = libseccomp.seccomp_rule_add_exact(self._ctx, action,
702 syscall_num, len(args),
703 c_arg[0],
704 c_arg[1],
705 c_arg[2],
706 c_arg[3],
707 c_arg[4],
708 c_arg[5])
709 else:
710 raise RuntimeError("Maximum number of arguments exceeded")
711 if rc != 0:
712 raise RuntimeError(str.format("Library error (errno = {0})", rc))
713
714 def export_pfc(self, file):
715 """ Export the filter in PFC format.
716
717 Arguments:
718 file - the output file
719
720 Description:
721 Output the filter in Pseudo Filter Code (PFC) to the given file.
722 The output is functionally equivalent to the BPF based filter
723 which is loaded into the Linux Kernel.
724 """
725 rc = libseccomp.seccomp_export_pfc(self._ctx, file.fileno())
726 if rc != 0:
727 raise RuntimeError(str.format("Library error (errno = {0})", rc))
728
729 def export_bpf(self, file):
730 """ Export the filter in BPF format.
731
732 Arguments:
733 file - the output file
734
735 Output the filter in Berkley Packet Filter (BPF) to the given
736 file. The output is identical to what is loaded into the
737 Linux Kernel.
738 """
739 rc = libseccomp.seccomp_export_bpf(self._ctx, file.fileno())
740 if rc != 0:
741 raise RuntimeError(str.format("Library error (errno = {0})", rc))
742
743 # kate: syntax python;
744 # kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;