diff options
Diffstat (limited to 'src/python')
-rw-r--r-- | src/python/Makefile.am | 52 | ||||
-rw-r--r-- | src/python/Makefile.in | 519 | ||||
-rw-r--r-- | src/python/libseccomp.pxd | 172 | ||||
-rw-r--r-- | src/python/seccomp.pyx | 1048 | ||||
-rwxr-xr-x | src/python/setup.py | 48 |
5 files changed, 1839 insertions, 0 deletions
diff --git a/src/python/Makefile.am b/src/python/Makefile.am new file mode 100644 index 0000000..5166412 --- /dev/null +++ b/src/python/Makefile.am @@ -0,0 +1,52 @@ +#### +# Seccomp Library Python Bindings +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License +# as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see <http://www.gnu.org/licenses>. +# + +PY_DISTUTILS = \ + VERSION_RELEASE="@PACKAGE_VERSION@" \ + CPPFLAGS="-I\${top_srcdir}/include ${AM_CPPFLAGS} ${CPPFLAGS}" \ + CFLAGS="${AM_CFLAGS} ${CFLAGS}" \ + LDFLAGS="${AM_LDFLAGS} ${LDFLAGS}" \ + ${PYTHON} ${srcdir}/setup.py + +# support silent builds +PY_BUILD_0 = @echo " PYTHON " $@; ${PY_DISTUTILS} -q build +PY_BUILD_1 = ${PY_DISTUTILS} build +PY_BUILD_ = ${PY_BUILD_0} +PY_BUILD = ${PY_BUILD_@AM_V@} + +PY_INSTALL = ${PY_DISTUTILS} install + +EXTRA_DIST = libseccomp.pxd seccomp.pyx setup.py + +all-local: build + +build: ../libseccomp.la libseccomp.pxd seccomp.pyx setup.py + [ ${srcdir} == ${builddir} ] || cp ${srcdir}/seccomp.pyx ${builddir} + ${PY_BUILD} && touch build + +install-exec-local: build + ${PY_INSTALL} --install-lib=${DESTDIR}/${pyexecdir} \ + --record=${DESTDIR}/${pyexecdir}/install_files.txt + +uninstall-local: + cat ${DESTDIR}/${pyexecdir}/install_files.txt | xargs ${RM} -f + ${RM} -f ${DESTDIR}/${pyexecdir}/install_files.txt + +clean-local: + [ ${srcdir} == ${builddir} ] || ${RM} -f ${builddir}/seccomp.pyx + ${RM} -rf seccomp.c build dist seccomp.egg-info diff --git a/src/python/Makefile.in b/src/python/Makefile.in new file mode 100644 index 0000000..de9800d --- /dev/null +++ b/src/python/Makefile.in @@ -0,0 +1,519 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +#### +# Seccomp Library Python Bindings +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License +# as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see <http://www.gnu.org/licenses>. +# +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +subdir = src/python +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/m4/ax_code_coverage.m4 \ + $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \ + $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \ + $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/configure.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +SOURCES = +DIST_SOURCES = +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +am__DIST_COMMON = $(srcdir)/Makefile.in +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_CFLAGS = @AM_CFLAGS@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AM_LDFLAGS = @AM_LDFLAGS@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CODE_COVERAGE_CFLAGS = @CODE_COVERAGE_CFLAGS@ +CODE_COVERAGE_CPPFLAGS = @CODE_COVERAGE_CPPFLAGS@ +CODE_COVERAGE_CXXFLAGS = @CODE_COVERAGE_CXXFLAGS@ +CODE_COVERAGE_ENABLED = @CODE_COVERAGE_ENABLED@ +CODE_COVERAGE_LDFLAGS = @CODE_COVERAGE_LDFLAGS@ +CODE_COVERAGE_LIBS = @CODE_COVERAGE_LIBS@ +CPPFLAGS = @CPPFLAGS@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +GCOV = @GCOV@ +GENHTML = @GENHTML@ +GPERF = @GPERF@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LCOV = @LCOV@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PYTHON = @PYTHON@ +PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@ +PYTHON_PLATFORM = @PYTHON_PLATFORM@ +PYTHON_PREFIX = @PYTHON_PREFIX@ +PYTHON_VERSION = @PYTHON_VERSION@ +RANLIB = @RANLIB@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +VERSION = @VERSION@ +VERSION_MAJOR = @VERSION_MAJOR@ +VERSION_MICRO = @VERSION_MICRO@ +VERSION_MINOR = @VERSION_MINOR@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +cython = @cython@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +have_coverity = @have_coverity@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +pkgpyexecdir = @pkgpyexecdir@ +pkgpythondir = @pkgpythondir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +pyexecdir = @pyexecdir@ +pythondir = @pythondir@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +PY_DISTUTILS = \ + VERSION_RELEASE="@PACKAGE_VERSION@" \ + CPPFLAGS="-I\${top_srcdir}/include ${AM_CPPFLAGS} ${CPPFLAGS}" \ + CFLAGS="${AM_CFLAGS} ${CFLAGS}" \ + LDFLAGS="${AM_LDFLAGS} ${LDFLAGS}" \ + ${PYTHON} ${srcdir}/setup.py + + +# support silent builds +PY_BUILD_0 = @echo " PYTHON " $@; ${PY_DISTUTILS} -q build +PY_BUILD_1 = ${PY_DISTUTILS} build +PY_BUILD_ = ${PY_BUILD_0} +PY_BUILD = ${PY_BUILD_@AM_V@} +PY_INSTALL = ${PY_DISTUTILS} install +EXTRA_DIST = libseccomp.pxd seccomp.pyx setup.py +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/python/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --foreign src/python/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +tags TAGS: + +ctags CTAGS: + +cscope cscopelist: + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile all-local +installdirs: +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-local mostlyclean-am + +distclean: distclean-am + -rm -f Makefile +distclean-am: clean-am distclean-generic + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-exec-local + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-local + +.MAKE: install-am install-strip + +.PHONY: all all-am all-local check check-am clean clean-generic \ + clean-libtool clean-local cscopelist-am ctags-am distclean \ + distclean-generic distclean-libtool distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-local install-html \ + install-html-am install-info install-info-am install-man \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags-am uninstall uninstall-am uninstall-local + +.PRECIOUS: Makefile + + +all-local: build + +build: ../libseccomp.la libseccomp.pxd seccomp.pyx setup.py + [ ${srcdir} == ${builddir} ] || cp ${srcdir}/seccomp.pyx ${builddir} + ${PY_BUILD} && touch build + +install-exec-local: build + ${PY_INSTALL} --install-lib=${DESTDIR}/${pyexecdir} \ + --record=${DESTDIR}/${pyexecdir}/install_files.txt + +uninstall-local: + cat ${DESTDIR}/${pyexecdir}/install_files.txt | xargs ${RM} -f + ${RM} -f ${DESTDIR}/${pyexecdir}/install_files.txt + +clean-local: + [ ${srcdir} == ${builddir} ] || ${RM} -f ${builddir}/seccomp.pyx + ${RM} -rf seccomp.c build dist seccomp.egg-info + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/src/python/libseccomp.pxd b/src/python/libseccomp.pxd new file mode 100644 index 0000000..0629bf1 --- /dev/null +++ b/src/python/libseccomp.pxd @@ -0,0 +1,172 @@ +# +# Seccomp Library Python Bindings +# +# Copyright (c) 2012,2013 Red Hat <pmoore@redhat.com> +# Author: Paul Moore <paul@paul-moore.com> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see <http://www.gnu.org/licenses>. +# + +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t + +cdef extern from "seccomp.h": + + cdef struct scmp_version: + unsigned int major + unsigned int minor + unsigned int micro + + ctypedef void* scmp_filter_ctx + + cdef enum: + SCMP_ARCH_NATIVE + SCMP_ARCH_X86 + SCMP_ARCH_X86_64 + SCMP_ARCH_X32 + SCMP_ARCH_ARM + SCMP_ARCH_AARCH64 + SCMP_ARCH_MIPS + SCMP_ARCH_MIPS64 + SCMP_ARCH_MIPS64N32 + SCMP_ARCH_MIPSEL + SCMP_ARCH_MIPSEL64 + SCMP_ARCH_MIPSEL64N32 + SCMP_ARCH_PARISC + SCMP_ARCH_PARISC64 + SCMP_ARCH_PPC + SCMP_ARCH_PPC64 + SCMP_ARCH_PPC64LE + SCMP_ARCH_S390 + SCMP_ARCH_S390X + SCMP_ARCH_RISCV64 + + cdef enum scmp_filter_attr: + SCMP_FLTATR_ACT_DEFAULT + SCMP_FLTATR_ACT_BADARCH + SCMP_FLTATR_CTL_NNP + SCMP_FLTATR_CTL_TSYNC + SCMP_FLTATR_API_TSKIP + SCMP_FLTATR_CTL_LOG + SCMP_FLTATR_CTL_SSB + SCMP_FLTATR_CTL_OPTIMIZE + SCMP_FLTATR_API_SYSRAWRC + + cdef enum scmp_compare: + SCMP_CMP_NE + SCMP_CMP_LT + SCMP_CMP_LE + SCMP_CMP_EQ + SCMP_CMP_GE + SCMP_CMP_GT + SCMP_CMP_MASKED_EQ + + cdef enum: + SCMP_ACT_KILL_PROCESS + SCMP_ACT_KILL + SCMP_ACT_TRAP + SCMP_ACT_LOG + SCMP_ACT_ALLOW + SCMP_ACT_NOTIFY + unsigned int SCMP_ACT_ERRNO(int errno) + unsigned int SCMP_ACT_TRACE(int value) + + ctypedef uint64_t scmp_datum_t + + cdef struct scmp_arg_cmp: + unsigned int arg + scmp_compare op + scmp_datum_t datum_a + scmp_datum_t datum_b + + cdef struct seccomp_data: + int nr + uint32_t arch + uint64_t instruction_pointer + uint64_t args[6] + + cdef struct seccomp_notif_sizes: + uint16_t seccomp_notif + uint16_t seccomp_notif_resp + uint16_t seccomp_data + + cdef struct seccomp_notif: + uint64_t id + uint32_t pid + uint32_t flags + seccomp_data data + + cdef struct seccomp_notif_resp: + uint64_t id + int64_t val + int32_t error + uint32_t flags + + scmp_version *seccomp_version() + + unsigned int seccomp_api_get() + int seccomp_api_set(unsigned int level) + + scmp_filter_ctx seccomp_init(uint32_t def_action) + int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action) + void seccomp_release(scmp_filter_ctx ctx) + + int seccomp_merge(scmp_filter_ctx ctx_dst, scmp_filter_ctx ctx_src) + + uint32_t seccomp_arch_resolve_name(char *arch_name) + uint32_t seccomp_arch_native() + int seccomp_arch_exist(scmp_filter_ctx ctx, int arch_token) + int seccomp_arch_add(scmp_filter_ctx ctx, int arch_token) + int seccomp_arch_remove(scmp_filter_ctx ctx, int arch_token) + + int seccomp_load(scmp_filter_ctx ctx) + + int seccomp_attr_get(scmp_filter_ctx ctx, + scmp_filter_attr attr, uint32_t* value) + int seccomp_attr_set(scmp_filter_ctx ctx, + scmp_filter_attr attr, uint32_t value) + + char *seccomp_syscall_resolve_num_arch(int arch_token, int num) + int seccomp_syscall_resolve_name_arch(int arch_token, char *name) + int seccomp_syscall_resolve_name_rewrite(int arch_token, char *name) + int seccomp_syscall_resolve_name(char *name) + int seccomp_syscall_priority(scmp_filter_ctx ctx, + int syscall, uint8_t priority) + + int seccomp_rule_add(scmp_filter_ctx ctx, uint32_t action, + int syscall, unsigned int arg_cnt, ...) + int seccomp_rule_add_array(scmp_filter_ctx ctx, + uint32_t action, int syscall, + unsigned int arg_cnt, + scmp_arg_cmp *arg_array) + int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action, + int syscall, unsigned int arg_cnt, ...) + int seccomp_rule_add_exact_array(scmp_filter_ctx ctx, + uint32_t action, int syscall, + unsigned int arg_cnt, + scmp_arg_cmp *arg_array) + + int seccomp_notify_alloc(seccomp_notif **req, seccomp_notif_resp **resp) + void seccomp_notify_free(seccomp_notif *req, seccomp_notif_resp *resp) + int seccomp_notify_receive(int fd, seccomp_notif *req) + int seccomp_notify_respond(int fd, seccomp_notif_resp *resp) + int seccomp_notify_id_valid(int fd, uint64_t id) + int seccomp_notify_fd(scmp_filter_ctx ctx) + + int seccomp_export_pfc(scmp_filter_ctx ctx, int fd) + int seccomp_export_bpf(scmp_filter_ctx ctx, int fd) + +# kate: syntax python; +# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off; diff --git a/src/python/seccomp.pyx b/src/python/seccomp.pyx new file mode 100644 index 0000000..2eeabc1 --- /dev/null +++ b/src/python/seccomp.pyx @@ -0,0 +1,1048 @@ +# +# Seccomp Library Python Bindings +# +# Copyright (c) 2012,2013,2017 Red Hat <pmoore@redhat.com> +# Author: Paul Moore <paul@paul-moore.com> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see <http://www.gnu.org/licenses>. +# + +# cython: language_level = 3str + +""" Python bindings for the libseccomp library + +The libseccomp library provides and easy to use, platform independent, +interface to the Linux Kernel's syscall filtering mechanism: seccomp. The +libseccomp API is designed to abstract away the underlying BPF based +syscall filter language and present a more conventional function-call +based filtering interface that should be familiar to, and easily adopted +by application developers. + +Filter action values: + KILL_PROCESS - kill the process + KILL - kill the thread + LOG - allow the syscall to be executed after the action has been logged + ALLOW - allow the syscall to execute + TRAP - a SIGSYS signal will be thrown + NOTIFY - a notification event will be sent via the notification API + ERRNO(x) - syscall will return (x) + TRACE(x) - if the process is being traced, (x) will be returned to the + tracing process via PTRACE_EVENT_SECCOMP and the + PTRACE_GETEVENTMSG option + +Argument comparison values (see the Arg class): + + NE - arg != datum_a + LT - arg < datum_a + LE - arg <= datum_a + EQ - arg == datum_a + GT - arg > datum_a + GE - arg >= datum_a + MASKED_EQ - (arg & datum_a) == datum_b + + +Example: + + import sys + from seccomp import * + + # create a filter object with a default KILL action + f = SyscallFilter(defaction=KILL) + + # add some basic syscalls which python typically wants + f.add_rule(ALLOW, "rt_sigaction") + f.add_rule(ALLOW, "rt_sigreturn") + f.add_rule(ALLOW, "exit_group") + f.add_rule(ALLOW, "brk") + + # add syscall filter rules to allow certain syscalls + f.add_rule(ALLOW, "open") + f.add_rule(ALLOW, "close") + f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno())) + f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno())) + f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno())) + + # load the filter into the kernel + f.load() +""" +__author__ = 'Paul Moore <paul@paul-moore.com>' +__date__ = "3 February 2017" + +from cpython.version cimport PY_MAJOR_VERSION +from libc.stdint cimport int8_t, int16_t, int32_t, int64_t +from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t +from libc.stdlib cimport free +import errno + +cimport libseccomp + +def c_str(string): + """ Convert a Python string to a C string. + + Arguments: + string - the Python string + + Description: + Convert the Python string into a form usable by C taking into consideration + the Python major version, e.g. Python 2.x or Python 3.x. + See http://docs.cython.org/en/latest/src/tutorial/strings.html for more + information. + """ + if PY_MAJOR_VERSION < 3: + return string + else: + return bytes(string, "ascii") + +KILL_PROCESS = libseccomp.SCMP_ACT_KILL_PROCESS +KILL = libseccomp.SCMP_ACT_KILL +TRAP = libseccomp.SCMP_ACT_TRAP +LOG = libseccomp.SCMP_ACT_LOG +ALLOW = libseccomp.SCMP_ACT_ALLOW +NOTIFY = libseccomp.SCMP_ACT_NOTIFY +def ERRNO(int errno): + """The action ERRNO(x) means that the syscall will return (x). + To conform to Linux syscall calling conventions, the syscall return + value should almost always be a negative number. + """ + return libseccomp.SCMP_ACT_ERRNO(errno) +def TRACE(int value): + """The action TRACE(x) means that, if the process is being traced, (x) + will be returned to the tracing process via PTRACE_EVENT_SECCOMP + and the PTRACE_GETEVENTMSG option. + """ + return libseccomp.SCMP_ACT_TRACE(value) + +NE = libseccomp.SCMP_CMP_NE +LT = libseccomp.SCMP_CMP_LT +LE = libseccomp.SCMP_CMP_LE +EQ = libseccomp.SCMP_CMP_EQ +GE = libseccomp.SCMP_CMP_GE +GT = libseccomp.SCMP_CMP_GT +MASKED_EQ = libseccomp.SCMP_CMP_MASKED_EQ + +def system_arch(): + """ Return the system architecture value. + + Description: + Returns the native system architecture value. + """ + return libseccomp.seccomp_arch_native() + +def resolve_syscall(arch, syscall): + """ Resolve the syscall. + + Arguments: + arch - the architecture value, e.g. Arch.* + syscall - the syscall name or number + + Description: + Resolve an architecture's syscall name to the correct number or the + syscall number to the correct name. + """ + cdef char *ret_str + + if isinstance(syscall, basestring): + return libseccomp.seccomp_syscall_resolve_name_rewrite(arch, + c_str(syscall)) + elif isinstance(syscall, int): + ret_str = libseccomp.seccomp_syscall_resolve_num_arch(arch, syscall) + if ret_str is NULL: + raise ValueError('Unknown syscall %d on arch %d' % (syscall, arch)) + else: + return ret_str + else: + raise TypeError("Syscall must either be an int or str type") + +def get_api(): + """ Query the level of API support + + Description: + Returns the API level value indicating the current supported + functionality. + """ + level = libseccomp.seccomp_api_get() + if level < 0: + raise RuntimeError(str.format("Library error (errno = {0})", level)) + + return level + +def set_api(unsigned int level): + """ Set the level of API support + + Arguments: + level - the API level + + Description: + This function forcibly sets the API level at runtime. General use + of this function is strongly discouraged. + """ + rc = libseccomp.seccomp_api_set(level) + if rc == -errno.EINVAL: + raise ValueError("Invalid level") + elif rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + +cdef class Arch: + """ Python object representing the SyscallFilter architecture values. + + Data values: + NATIVE - the native architecture + X86 - 32-bit x86 + X86_64 - 64-bit x86 + X32 - 64-bit x86 using the x32 ABI + ARM - ARM + AARCH64 - 64-bit ARM + MIPS - MIPS O32 ABI + MIPS64 - MIPS 64-bit ABI + MIPS64N32 - MIPS N32 ABI + MIPSEL - MIPS little endian O32 ABI + MIPSEL64 - MIPS little endian 64-bit ABI + MIPSEL64N32 - MIPS little endian N32 ABI + PARISC - 32-bit PA-RISC + PARISC64 - 64-bit PA-RISC + PPC64 - 64-bit PowerPC + PPC - 32-bit PowerPC + RISCV64 - 64-bit RISC-V + """ + + cdef int _token + + NATIVE = libseccomp.SCMP_ARCH_NATIVE + X86 = libseccomp.SCMP_ARCH_X86 + X86_64 = libseccomp.SCMP_ARCH_X86_64 + X32 = libseccomp.SCMP_ARCH_X32 + ARM = libseccomp.SCMP_ARCH_ARM + AARCH64 = libseccomp.SCMP_ARCH_AARCH64 + MIPS = libseccomp.SCMP_ARCH_MIPS + MIPS64 = libseccomp.SCMP_ARCH_MIPS64 + MIPS64N32 = libseccomp.SCMP_ARCH_MIPS64N32 + MIPSEL = libseccomp.SCMP_ARCH_MIPSEL + MIPSEL64 = libseccomp.SCMP_ARCH_MIPSEL64 + MIPSEL64N32 = libseccomp.SCMP_ARCH_MIPSEL64N32 + PARISC = libseccomp.SCMP_ARCH_PARISC + PARISC64 = libseccomp.SCMP_ARCH_PARISC64 + PPC = libseccomp.SCMP_ARCH_PPC + PPC64 = libseccomp.SCMP_ARCH_PPC64 + PPC64LE = libseccomp.SCMP_ARCH_PPC64LE + S390 = libseccomp.SCMP_ARCH_S390 + S390X = libseccomp.SCMP_ARCH_S390X + RISCV64 = libseccomp.SCMP_ARCH_RISCV64 + + def __cinit__(self, arch=libseccomp.SCMP_ARCH_NATIVE): + """ Initialize the architecture object. + + Arguments: + arch - the architecture name or token value + + Description: + Create an architecture object using the given name or token value. + """ + if isinstance(arch, int): + if arch == libseccomp.SCMP_ARCH_NATIVE: + self._token = libseccomp.seccomp_arch_native() + elif arch == libseccomp.SCMP_ARCH_X86: + self._token = libseccomp.SCMP_ARCH_X86 + elif arch == libseccomp.SCMP_ARCH_X86_64: + self._token = libseccomp.SCMP_ARCH_X86_64 + elif arch == libseccomp.SCMP_ARCH_X32: + self._token = libseccomp.SCMP_ARCH_X32 + elif arch == libseccomp.SCMP_ARCH_ARM: + self._token = libseccomp.SCMP_ARCH_ARM + elif arch == libseccomp.SCMP_ARCH_AARCH64: + self._token = libseccomp.SCMP_ARCH_AARCH64 + elif arch == libseccomp.SCMP_ARCH_MIPS: + self._token = libseccomp.SCMP_ARCH_MIPS + elif arch == libseccomp.SCMP_ARCH_MIPS64: + self._token = libseccomp.SCMP_ARCH_MIPS64 + elif arch == libseccomp.SCMP_ARCH_MIPS64N32: + self._token = libseccomp.SCMP_ARCH_MIPS64N32 + elif arch == libseccomp.SCMP_ARCH_MIPSEL: + self._token = libseccomp.SCMP_ARCH_MIPSEL + elif arch == libseccomp.SCMP_ARCH_MIPSEL64: + self._token = libseccomp.SCMP_ARCH_MIPSEL64 + elif arch == libseccomp.SCMP_ARCH_MIPSEL64N32: + self._token = libseccomp.SCMP_ARCH_MIPSEL64N32 + elif arch == libseccomp.SCMP_ARCH_PARISC: + self._token = libseccomp.SCMP_ARCH_PARISC + elif arch == libseccomp.SCMP_ARCH_PARISC64: + self._token = libseccomp.SCMP_ARCH_PARISC64 + elif arch == libseccomp.SCMP_ARCH_PPC: + self._token = libseccomp.SCMP_ARCH_PPC + elif arch == libseccomp.SCMP_ARCH_PPC64: + self._token = libseccomp.SCMP_ARCH_PPC64 + elif arch == libseccomp.SCMP_ARCH_PPC64LE: + self._token = libseccomp.SCMP_ARCH_PPC64LE + elif arch == libseccomp.SCMP_ARCH_S390: + self._token = libseccomp.SCMP_ARCH_S390 + elif arch == libseccomp.SCMP_ARCH_S390X: + self._token = libseccomp.SCMP_ARCH_S390X + else: + self._token = 0; + elif isinstance(arch, basestring): + self._token = libseccomp.seccomp_arch_resolve_name(c_str(arch)) + else: + raise TypeError("Architecture must be an int or str type") + if self._token == 0: + raise ValueError("Invalid architecture") + + def __int__(self): + """ Convert the architecture object to a token value. + + Description: + Convert the architecture object to an integer representing the + architecture's token value. + """ + return self._token + +cdef class Attr: + """ Python object representing the SyscallFilter attributes. + + Data values: + ACT_DEFAULT - the filter's default action + ACT_BADARCH - the filter's bad architecture action + CTL_NNP - the filter's "no new privileges" flag + CTL_NNP - the filter's thread sync flag + CTL_TSYNC - sync threads on filter load + CTL_TSKIP - allow rules with a -1 syscall number + CTL_LOG - log not-allowed actions + CTL_SSB - disable SSB mitigations + CTL_OPTIMIZE - the filter's optimization level: + 0: currently unused + 1: rules weighted by priority and complexity (DEFAULT) + 2: binary tree sorted by syscall number + API_SYSRAWRC - return the raw syscall codes + """ + ACT_DEFAULT = libseccomp.SCMP_FLTATR_ACT_DEFAULT + ACT_BADARCH = libseccomp.SCMP_FLTATR_ACT_BADARCH + CTL_NNP = libseccomp.SCMP_FLTATR_CTL_NNP + CTL_TSYNC = libseccomp.SCMP_FLTATR_CTL_TSYNC + API_TSKIP = libseccomp.SCMP_FLTATR_API_TSKIP + CTL_LOG = libseccomp.SCMP_FLTATR_CTL_LOG + CTL_SSB = libseccomp.SCMP_FLTATR_CTL_SSB + CTL_OPTIMIZE = libseccomp.SCMP_FLTATR_CTL_OPTIMIZE + API_SYSRAWRC = libseccomp.SCMP_FLTATR_API_SYSRAWRC + +cdef class Arg: + """ Python object representing a SyscallFilter syscall argument. + """ + cdef libseccomp.scmp_arg_cmp _arg + + def __cinit__(self, arg, op, datum_a, datum_b = 0): + """ Initialize the argument comparison. + + Arguments: + arg - the argument number, starting at 0 + op - the argument comparison operator, e.g. {NE,LT,LE,...} + datum_a - argument value + datum_b - argument value, only valid when op == MASKED_EQ + + Description: + Create an argument comparison object for use with SyscallFilter. + """ + self._arg.arg = arg + self._arg.op = op + self._arg.datum_a = datum_a + self._arg.datum_b = datum_b + + cdef libseccomp.scmp_arg_cmp to_c(self): + """ Convert the object into a C structure. + + Description: + Helper function which should only be used internally by + SyscallFilter objects and exists for the sole purpose of making it + easier to deal with the varadic functions of the libseccomp API, + e.g. seccomp_rule_add(). + """ + return self._arg + +cdef class Notification: + """ Python object representing a seccomp notification. + """ + cdef uint64_t _id + cdef uint32_t _pid + cdef uint32_t _flags + cdef int _syscall + cdef uint32_t _syscall_arch + cdef uint64_t _syscall_ip + cdef uint64_t _syscall_args[6] + + def __cinit__(self, id, pid, flags, syscall, arch, ip, args): + """ Initialize the notification. + + Arguments: + id - the notification ID + pid - the process ID + flags - the notification flags + syscall - the syscall number + ip - the instruction pointer + args - list of the six syscall arguments + + Description: + Create a seccomp Notification object. + """ + self._id = id + self._pid = pid + self._flags = flags + self._syscall = syscall + self._syscall_arch = arch + self._syscall_ip = ip + self._syscall_args[0] = args[0] + self._syscall_args[1] = args[1] + self._syscall_args[2] = args[2] + self._syscall_args[3] = args[3] + self._syscall_args[4] = args[4] + self._syscall_args[5] = args[5] + + @property + def id(self): + """ Get the seccomp notification ID. + + Description: + Get the seccomp notification ID. + """ + return self._id + + @property + def pid(self): + """ Get the seccomp notification process ID. + + Description: + Get the seccomp notification process ID. + """ + return self._pid + + @property + def flags(self): + """ Get the seccomp notification flags. + + Description: + Get the seccomp notification flags. + """ + return self._flags + + @property + def syscall(self): + """ Get the seccomp notification syscall. + + Description: + Get the seccomp notification syscall. + """ + return self._syscall + + @property + def syscall_arch(self): + """ Get the seccomp notification syscall architecture. + + Description: + Get the seccomp notification syscall architecture. + """ + return self._syscall_arch + + @property + def syscall_ip(self): + """ Get the seccomp notification syscall instruction pointer. + + Description: + Get the seccomp notification syscall instruction pointer. + """ + return self._syscall_ip + + @property + def syscall_args(self): + """ Get the seccomp notification syscall arguments. + + Description: + Get the seccomp notification syscall arguments in a six element list. + """ + return [self._syscall_args[0], self._syscall_args[1], + self._syscall_args[2], self._syscall_args[3], + self._syscall_args[4], self._syscall_args[5]] + +cdef class NotificationResponse: + """ Python object representing a seccomp notification response. + """ + cdef uint64_t _id + cdef int64_t _val + cdef int32_t _error + cdef uint32_t _flags + + def __cinit__(self, notify, val = 0, error = 0, flags = 0): + """ Initialize the notification response. + + Arguments: + notify - a Notification object + val - the notification response value + error - the notification response error + flags - the notification response flags + + Description: + Create a seccomp NotificationResponse object. + """ + self._id = notify.id + self._val = val + self._error = error + self._flags = flags + + @property + def id(self): + """ Get the seccomp notification response ID. + + Description: + Get the seccomp notification response ID. + """ + return self._id + + @id.setter + def id(self, value): + """ Set the seccomp notification response ID. + + Arguments: + id - the notification response ID + + Description: + Set the seccomp notification response ID. + """ + self._id = value + + @property + def val(self): + """ Get the seccomp notification response value. + + Description: + Get the seccomp notification response value. + """ + return self._val + + @val.setter + def val(self, value): + """ Set the seccomp notification response value. + + Arguments: + val - the notification response value + + Description: + Set the seccomp notification response value. + """ + self._val = value + + @property + def error(self): + """ Get the seccomp notification response error. + + Description: + Get the seccomp notification response error. + """ + return self._error + + @error.setter + def error(self, value): + """ Set the seccomp notification response error. + + Arguments: + error - the notification response error + + Description: + Set the seccomp notification response error. + """ + self._error = value + + @property + def flags(self): + """ Get the seccomp notification response flags. + + Description: + Get the seccomp notification response flags. + """ + return self._flags + + @flags.setter + def flags(self, value): + """ Set the seccomp notification response flags. + + Arguments: + flags - the notification response flags + + Description: + Set the seccomp notification response flags. + """ + self._flags = value + +cdef class SyscallFilter: + """ Python object representing a seccomp syscall filter. """ + cdef int _defaction + cdef libseccomp.scmp_filter_ctx _ctx + + def __cinit__(self, int defaction): + self._ctx = libseccomp.seccomp_init(defaction) + if self._ctx == NULL: + raise RuntimeError("Library error") + _defaction = defaction + + def __init__(self, defaction): + """ Initialize the filter state + + Arguments: + defaction - the default filter action + + Description: + Initializes the seccomp filter state to the defaults. + """ + + def __dealloc__(self): + """ Destroys the filter state and releases any resources. + + Description: + Destroys the seccomp filter state and releases any resources + associated with the filter state. This function does not affect + any seccomp filters already loaded into the kernel. + """ + if self._ctx != NULL: + libseccomp.seccomp_release(self._ctx) + + def reset(self, int defaction = -1): + """ Reset the filter state. + + Arguments: + defaction - the default filter action + + Description: + Resets the seccomp filter state to an initial default state, if a + default filter action is not specified in the reset call the + original action will be reused. This function does not affect any + seccomp filters alread loaded into the kernel. + """ + if defaction == -1: + defaction = self._defaction + rc = libseccomp.seccomp_reset(self._ctx, defaction) + if rc == -errno.EINVAL: + raise ValueError("Invalid action") + if rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + _defaction = defaction + + def merge(self, SyscallFilter filter): + """ Merge two existing SyscallFilter objects. + + Arguments: + filter - a valid SyscallFilter object + + Description: + Merges a valid SyscallFilter object with the current SyscallFilter + object; the passed filter object will be reset on success. In + order to successfully merge two seccomp filters they must have the + same attribute values and not share any of the same architectures. + """ + rc = libseccomp.seccomp_merge(self._ctx, filter._ctx) + if rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + filter._ctx = NULL + filter = SyscallFilter(filter._defaction) + + def exist_arch(self, arch): + """ Check if the seccomp filter contains a given architecture. + + Arguments: + arch - the architecture value, e.g. Arch.* + + Description: + Test to see if a given architecture is included in the filter. + Return True is the architecture exists, False if it does not + exist. + """ + rc = libseccomp.seccomp_arch_exist(self._ctx, arch) + if rc == 0: + return True + elif rc == -errno.EEXIST: + return False + elif rc == -errno.EINVAL: + raise ValueError("Invalid architecture") + else: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def add_arch(self, arch): + """ Add an architecture to the filter. + + Arguments: + arch - the architecture value, e.g. Arch.* + + Description: + Add the given architecture to the filter. Any new rules added + after this method returns successfully will be added to this new + architecture, but any existing rules will not be added to the new + architecture. + """ + rc = libseccomp.seccomp_arch_add(self._ctx, arch) + if rc == -errno.EINVAL: + raise ValueError("Invalid architecture") + elif rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def remove_arch(self, arch): + """ Remove an architecture from the filter. + + Arguments: + arch - the architecture value, e.g. Arch.* + + Description: + Remove the given architecture from the filter. The filter must + always contain at least one architecture, so if only one + architecture exists in the filter this method will fail. + """ + rc = libseccomp.seccomp_arch_remove(self._ctx, arch) + if rc == -errno.EINVAL: + raise ValueError("Invalid architecture") + elif rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def load(self): + """ Load the filter into the Linux Kernel. + + Description: + Load the current filter into the Linux Kernel. As soon as the + method returns the filter will be active and enforcing. + """ + rc = libseccomp.seccomp_load(self._ctx) + if rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def get_attr(self, attr): + """ Get an attribute value from the filter. + + Arguments: + attr - the attribute, e.g. Attr.* + + Description: + Lookup the given attribute in the filter and return the + attribute's value to the caller. + """ + cdef uint32_t value = 0 + rc = libseccomp.seccomp_attr_get(self._ctx, + attr, <uint32_t *>&value) + if rc == -errno.EINVAL: + raise ValueError("Invalid attribute") + elif rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + return value + + def set_attr(self, attr, int value): + """ Set a filter attribute. + + Arguments: + attr - the attribute, e.g. Attr.* + value - the attribute value + + Description: + Lookup the given attribute in the filter and assign it the given + value. + """ + rc = libseccomp.seccomp_attr_set(self._ctx, attr, value) + if rc == -errno.EINVAL: + raise ValueError("Invalid attribute") + elif rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def syscall_priority(self, syscall, int priority): + """ Set the filter priority of a syscall. + + Arguments: + syscall - the syscall name or number + priority - the priority of the syscall + + Description: + Set the filter priority of the given syscall. A syscall with a + higher priority will have less overhead in the generated filter + code which is loaded into the system. Priority values can range + from 0 to 255 inclusive. + """ + if priority < 0 or priority > 255: + raise ValueError("Syscall priority must be between 0 and 255") + if isinstance(syscall, str): + syscall_str = syscall.encode() + syscall_num = libseccomp.seccomp_syscall_resolve_name(syscall_str) + elif isinstance(syscall, int): + syscall_num = syscall + else: + raise TypeError("Syscall must either be an int or str type") + rc = libseccomp.seccomp_syscall_priority(self._ctx, + syscall_num, priority) + if rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def add_rule(self, int action, syscall, *args): + """ Add a new rule to filter. + + Arguments: + action - the rule action: KILL_PROCESS, KILL, TRAP, ERRNO(), TRACE(), + LOG, or ALLOW + syscall - the syscall name or number + args - variable number of Arg objects + + Description: + Add a new rule to the filter, matching on the given syscall and an + optional list of argument comparisons. If the rule is triggered + the given action will be taken by the kernel. In order for the + rule to trigger, the syscall as well as each argument comparison + must be true. + + In the case where the specific rule is not valid on a specific + architecture, e.g. socket() on 32-bit x86, this method rewrites + the rule to the best possible match. If you don't want this fule + rewriting to take place use add_rule_exactly(). + """ + cdef libseccomp.scmp_arg_cmp c_arg[6] + if isinstance(syscall, str): + syscall_str = syscall.encode() + syscall_num = libseccomp.seccomp_syscall_resolve_name(syscall_str) + elif isinstance(syscall, int): + syscall_num = syscall + else: + raise TypeError("Syscall must either be an int or str type") + """ NOTE: the code below exists solely to deal with the varadic + nature of seccomp_rule_add() function and the inability of Cython + to handle this automatically """ + if len(args) > 6: + raise RuntimeError("Maximum number of arguments exceeded") + cdef Arg arg + for i, arg in enumerate(args): + c_arg[i] = arg.to_c() + if len(args) == 0: + rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num, 0) + elif len(args) == 1: + rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num, + len(args), + c_arg[0]) + elif len(args) == 2: + rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num, + len(args), + c_arg[0], + c_arg[1]) + elif len(args) == 3: + rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num, + len(args), + c_arg[0], + c_arg[1], + c_arg[2]) + elif len(args) == 4: + rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num, + len(args), + c_arg[0], + c_arg[1], + c_arg[2], + c_arg[3]) + elif len(args) == 5: + rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num, + len(args), + c_arg[0], + c_arg[1], + c_arg[2], + c_arg[3], + c_arg[4]) + elif len(args) == 6: + rc = libseccomp.seccomp_rule_add(self._ctx, action, syscall_num, + len(args), + c_arg[0], + c_arg[1], + c_arg[2], + c_arg[3], + c_arg[4], + c_arg[5]) + else: + raise RuntimeError("Maximum number of arguments exceeded") + if rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def add_rule_exactly(self, int action, syscall, *args): + """ Add a new rule to filter. + + Arguments: + action - the rule action: KILL_PROCESS, KILL, TRAP, ERRNO(), TRACE(), + LOG, or ALLOW + syscall - the syscall name or number + args - variable number of Arg objects + + Description: + Add a new rule to the filter, matching on the given syscall and an + optional list of argument comparisons. If the rule is triggered + the given action will be taken by the kernel. In order for the + rule to trigger, the syscall as well as each argument comparison + must be true. + + This method attempts to add the filter rule exactly as specified + which can cause problems on certain architectures, e.g. socket() + on 32-bit x86. For a architecture independent version of this + method use add_rule(). + """ + cdef libseccomp.scmp_arg_cmp c_arg[6] + if isinstance(syscall, str): + syscall_str = syscall.encode() + syscall_num = libseccomp.seccomp_syscall_resolve_name(syscall_str) + elif isinstance(syscall, int): + syscall_num = syscall + else: + raise TypeError("Syscall must either be an int or str type") + """ NOTE: the code below exists solely to deal with the varadic + nature of seccomp_rule_add_exact() function and the inability of + Cython to handle this automatically """ + if len(args) > 6: + raise RuntimeError("Maximum number of arguments exceeded") + cdef Arg arg + for i, arg in enumerate(args): + c_arg[i] = arg.to_c() + if len(args) == 0: + rc = libseccomp.seccomp_rule_add_exact(self._ctx, action, + syscall_num, 0) + elif len(args) == 1: + rc = libseccomp.seccomp_rule_add_exact(self._ctx, action, + syscall_num, len(args), + c_arg[0]) + elif len(args) == 2: + rc = libseccomp.seccomp_rule_add_exact(self._ctx, action, + syscall_num, len(args), + c_arg[0], + c_arg[1]) + elif len(args) == 3: + rc = libseccomp.seccomp_rule_add_exact(self._ctx, action, + syscall_num, len(args), + c_arg[0], + c_arg[1], + c_arg[2]) + elif len(args) == 4: + rc = libseccomp.seccomp_rule_add_exact(self._ctx, action, + syscall_num, len(args), + c_arg[0], + c_arg[1], + c_arg[2], + c_arg[3]) + elif len(args) == 5: + rc = libseccomp.seccomp_rule_add_exact(self._ctx, action, + syscall_num, len(args), + c_arg[0], + c_arg[1], + c_arg[2], + c_arg[3], + c_arg[4]) + elif len(args) == 6: + rc = libseccomp.seccomp_rule_add_exact(self._ctx, action, + syscall_num, len(args), + c_arg[0], + c_arg[1], + c_arg[2], + c_arg[3], + c_arg[4], + c_arg[5]) + else: + raise RuntimeError("Maximum number of arguments exceeded") + if rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def receive_notify(self): + """ Receive seccomp notifications. + + Description: + Receive a seccomp notification from the system, requires the use of + the NOTIFY action. + """ + cdef libseccomp.seccomp_notif *req + + fd = libseccomp.seccomp_notify_fd(self._ctx) + if fd < 0: + raise RuntimeError("Notifications not enabled/active") + rc = libseccomp.seccomp_notify_alloc(&req, NULL) + if rc < 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + rc = libseccomp.seccomp_notify_receive(fd, req) + if rc < 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + rc = libseccomp.seccomp_notify_id_valid(fd, req.id) + if rc < 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + notify = Notification(req.id, req.pid, req.flags, req.data.nr, + req.data.arch, req.data.instruction_pointer, + [req.data.args[0], req.data.args[1], + req.data.args[2], req.data.args[3], + req.data.args[4], req.data.args[5]]) + free(req) + return notify + + def respond_notify(self, response): + """ Send a seccomp notification response. + + Arguments: + response - the response to send to the system + + Description: + Respond to a seccomp notification. + """ + cdef libseccomp.seccomp_notif_resp *resp + + fd = libseccomp.seccomp_notify_fd(self._ctx) + if fd < 0: + raise RuntimeError("Notifications not enabled/active") + rc = libseccomp.seccomp_notify_alloc(NULL, &resp) + if rc < 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + resp.id = response.id + resp.val = response.val + resp.error = response.error + resp.flags = response.flags + rc = libseccomp.seccomp_notify_respond(fd, resp) + if rc < 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def get_notify_fd(self): + """ Get the seccomp notification file descriptor + + Description: + Returns the seccomp listener file descriptor that was generated when + the seccomp policy was loaded. This is only valid after load() with a + filter that makes use of the NOTIFY action. + """ + fd = libseccomp.seccomp_notify_fd(self._ctx) + if fd < 0: + raise RuntimeError("Notifications not enabled/active") + return fd + + def export_pfc(self, file): + """ Export the filter in PFC format. + + Arguments: + file - the output file + + Description: + Output the filter in Pseudo Filter Code (PFC) to the given file. + The output is functionally equivalent to the BPF based filter + which is loaded into the Linux Kernel. + """ + rc = libseccomp.seccomp_export_pfc(self._ctx, file.fileno()) + if rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + + def export_bpf(self, file): + """ Export the filter in BPF format. + + Arguments: + file - the output file + + Description: + Output the filter in Berkeley Packet Filter (BPF) to the given + file. The output is identical to what is loaded into the + Linux Kernel. + """ + rc = libseccomp.seccomp_export_bpf(self._ctx, file.fileno()) + if rc != 0: + raise RuntimeError(str.format("Library error (errno = {0})", rc)) + +# kate: syntax python; +# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off; diff --git a/src/python/setup.py b/src/python/setup.py new file mode 100755 index 0000000..0419111 --- /dev/null +++ b/src/python/setup.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python + +# +# Enhanced Seccomp Library Python Module Build Script +# +# Copyright (c) 2012 Red Hat <pmoore@redhat.com> +# Author: Paul Moore <paul@paul-moore.com> +# + +# +# This library is free software; you can redistribute it and/or modify it +# under the terms of version 2.1 of the GNU Lesser General Public License as +# published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +# for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this library; if not, see <http://www.gnu.org/licenses>. +# + +import os + +from distutils.core import setup +from distutils.extension import Extension +from Cython.Distutils import build_ext + +setup( + name = "seccomp", + version = os.environ["VERSION_RELEASE"], + description = "Python binding for libseccomp", + long_description = "Python API for the Linux Kernel's syscall filtering capability, seccomp.", + url = "https://github.com/seccomp/libseccomp", + maintainer = "Paul Moore", + maintainer_email = "paul@paul-moore.com", + license = "LGPLv2.1", + platforms = "Linux", + cmdclass = {'build_ext': build_ext}, + ext_modules = [ + Extension("seccomp", ["seccomp.pyx"], + # unable to handle libtool libraries directly + extra_objects=["../.libs/libseccomp.a"], + # fix build warnings, see PEP 3123 + extra_compile_args=["-fno-strict-aliasing"]) + ] +) |