--- /dev/null
+libseccomp: Releases
+===============================================================================
+http://libseccomp.sf.net
+
+* Version 2.1.1 - October 31, 2013
+- Build system improvements
+- Automated test improvments, including a "check" target for use by
+ packagers to verify the build
+- Numerous bug fixes related to the filter's internal rule database which
+ affect those creating rules with syscall arguments
+- Introduced tools to verify the style/formatting of the code, including a
+ "check-syntax" target for use by developers
+- Non-public symbols are now hidden in the library
+
+* Version 2.1.0 - June 11, 2013
+- Add support for the x32 and ARM architectures
+- Improvements to the regression tests, including support for live tests
+- More verbose PFC output, including translation of syscall numbers to names
+- Several assorted bugfixes affecting the seccomp BPF generation
+- The syscall number/name resolver tool is now available to install
+
+* Version 2.0.0 - January 28, 2013
+- Fixes for the x86 multiplexed syscalls
+- Additions to the API to better support non-native architecures
+- Additions to the API to support multiple architecures in one filter
+- Additions to the API to resolve syscall name/number mappings
+- Assorted minor bug fixes
+- Improved build messages regardless of build verbosity
+- More automated tests added as well as a number of improvements to the test
+ harness
+
+* Version 1.0.1 - November 12, 2012
+- The header file is now easier to use with C++ compilers
+- Minor documentation fixes
+- Minor memory leak fixes
+- Corrected x86 filter generation on x86_64 systems
+- Corrected problems with small filters and filters with arguments
+
+* Version 1.0.0 - July 31, 2012
+- Change the API to be context-aware; eliminates all internal state but breaks
+ compatibility with the previous 0.1.0 release
+- Added support for multiple build jobs ("make -j8") and verbose builds using
+ the "V=1" build variable ("make V=1")
+- Minor tweaks to the regression test script output
+
+* Version 0.1.0 - June 8, 2012
+- Initial release
--- /dev/null
+libseccomp: Contributors
+===============================================================================
+http://libseccomp.sf.net
+
+Andy Lutomirski <luto@amacapital.net>
+Ashley Lai <adlai@us.ibm.com>
+Corey Bryant <coreyb@linux.vnet.ibm.com>
+Eduardo Otubo <otubo@linux.vnet.ibm.com>
+Eric Paris <eparis@redhat.com>
+Jake Edge <jake@lwn.net>
+Joe MacDonald <joe@deserted.net>
+Kees Cook <keescook@chromium.org>
+Paul Moore <pmoore@redhat.com>
+Thiago Marcos P. Santos <thiago.santos@intel.com>
+Vitaly Vi Shukela <vi0oss@gmail.com>
--- /dev/null
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
--- /dev/null
+#
+# Enhanced Seccomp Library Makefile
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+#
+# macros
+#
+
+include macros.mk
+
+#
+# configuration
+#
+
+-include version_info.mk
+-include configure.mk
+include install.mk
+
+#
+# targets
+#
+
+CONFIGS = configure.mk configure.h version_info.mk libseccomp.pc
+SUBDIRS_BUILD = include src tests tools
+SUBDIRS_INSTALL = include src tools doc
+
+.PHONY: tarball install check check-syntax ctags cstags clean dist-clean \
+ $(SUBDIRS_BUILD)
+
+all: $(SUBDIRS_BUILD)
+
+$(CONFIGS): version_info
+ @$(ECHO_INFO) "automatically generating configuration ..."
+ @./configure
+
+tarball: dist-clean
+ @ver=$(VERSION_RELEASE); \
+ tarball=libseccomp-$$ver.tar.gz; \
+ $(ECHO_INFO) "creating the tarball ../$$tarball"; \
+ tmp_dir=$$(mktemp -d /tmp/libseccomp.XXXXX); \
+ rel_dir=$$tmp_dir/libseccomp-$$ver; \
+ $(MKDIR) $$rel_dir; \
+ $(TAR) cf - --exclude=*~ --exclude=.git* --exclude=.stgit* . | \
+ (cd $$rel_dir; tar xf -); \
+ (cd $$tmp_dir; $(TAR) zcf $$tarball libseccomp-$$ver); \
+ $(MV) $$tmp_dir/$$tarball ..; \
+ $(RM) -rf $$tmp_dir;
+
+$(VERSION_HDR): version_info.mk
+ @$(ECHO_INFO) "creating the version header file"
+ @hdr="$(VERSION_HDR)"; \
+ $(ECHO) "/* automatically generated - do not edit */" > $$hdr; \
+ $(ECHO) "#ifndef _VERSION_H" >> $$hdr; \
+ $(ECHO) "#define _VERSION_H" >> $$hdr; \
+ $(ECHO) "#define VERSION_RELEASE \"$(VERSION_RELEASE)\"" >> $$hdr; \
+ $(ECHO) "#define VERSION_MAJOR $(VERSION_MAJOR)" >> $$hdr; \
+ $(ECHO) "#define VERSION_MINOR $(VERSION_MINOR)" >> $$hdr; \
+ $(ECHO) "#define VERSION_MICRO $(VERSION_MICRO)" >> $$hdr; \
+ $(ECHO) "#endif" >> $$hdr;
+
+include: $(VERSION_HDR) $(CONFIGS)
+ @$(ECHO_INFO) "building in directory $@/ ..."
+ @$(MAKE) -C $@
+
+src: $(VERSION_HDR) $(CONFIGS) include
+ @$(ECHO_INFO) "building in directory $@/ ..."
+ @$(MAKE) -C $@
+
+tests: src include
+ @$(ECHO_INFO) "building in directory $@/ ..."
+ @$(MAKE) -C $@
+
+tools: src include
+ @$(ECHO_INFO) "building in directory $@/ ..."
+ @$(MAKE) -C $@
+
+install: $(SUBDIRS_BUILD)
+ @$(ECHO_INFO) "installing in $(INSTALL_PREFIX) ..."
+ $(INSTALL_PC_MACRO) libseccomp.pc
+ @for dir in $(SUBDIRS_INSTALL); do \
+ $(ECHO_INFO) "installing from $$dir/"; \
+ $(MAKE) -C $$dir install; \
+ done
+
+check: tools tests
+ @$(ECHO_INFO) "checking in directory tests/ ..."
+ @$(MAKE) -C tests check
+
+check-syntax:
+ @./tools/check-syntax
+
+ctags:
+ @$(ECHO_INFO) "generating ctags for the project ..."
+ @ctags -R *
+
+cstags:
+ @$(ECHO_INFO) "generating cscope tags for the project ..."
+ @find -iname *.[ch] > cscope.files
+ @cscope -b -q -k
+
+clean:
+ @$(ECHO_INFO) "cleaning up libseccomp"
+ @for dir in $(SUBDIRS_BUILD); do \
+ $(MAKE) -C $$dir clean; \
+ done
+
+dist-clean: clean
+ @$(ECHO_INFO) "removing the configuration files"
+ @$(RM) $(CONFIGS)
--- /dev/null
+libseccomp: An Enhanced Seccomp (mode 2) Helper Library
+===============================================================================
+http://libseccomp.sf.net
+
+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.
+
+* Documentation
+
+The "doc/" directory contains all of the documentation aside from the README
+file (this file) and the LICENSE file which can be found in the top level
+directory.
+
+* Building and Installing the Library
+
+In order to build the library you should follow the familiar three step
+process used by most applications:
+
+ # ./configure
+ # make [V=0|1]
+ # make install
+
+As usual, running "./configure -h" will display a list of build-time
+configuration options.
+
+* Testing the Library
+
+There are a number of tests located in the "tests/" directory and a script
+which can be used to help automate their execution, "regression". If you want
+to run all of the tests you can simply run the script:
+
+ # ./configure
+ # make
+ # cd tests
+ # ./regression
+
+However, the script takes a number of options to customize its execution; the
+options can be displayed by running "./regression -h".
+
+* Other Useful Tools
+
+The "tools/" directory includes a number of tools which may be helpful in the
+development of the library, or applications using the library, but for various
+reasons are not installed by default.
--- /dev/null
+#!/bin/bash
+
+#
+# Enhanced Seccomp Library Configure Script
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+# configuration defaults
+opt_prefix="/usr/local"
+opt_libdir=""
+opt_sysinc_seccomp="yes"
+opt_bindings_python="no"
+
+# output files
+cnf_mk_file="configure.mk"
+cnf_h_file="configure.h"
+
+####
+# functions
+
+function test_deps() {
+ [[ -z "$1" ]] && return 0
+ which "$1" >& /dev/null && return 0
+ return 1
+}
+
+function verify_deps() {
+ [[ -z "$1" ]] && return
+ if ! test_deps "$1"; then
+ echo "error: install \"$1\" and include it in your \$PATH"
+ exit 1
+ fi
+}
+
+function msg_usage() {
+ cat << EOF
+Configure the enhanced seccomp library, libseccomp, for this system.
+
+Usage:
+ ./configure <options>
+
+Options:
+* general configuration
+ -h, --help display this help and exit
+* installation configuration
+ --prefix=PREFIX installation base [/usr/local]
+ --libdir=DIR library directory [/usr/local/lib]
+EOF
+}
+
+function msg_summary() {
+ cat << EOF
+ CONFIGURATION SUMMARY
+ libseccomp version: ${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}
+ installation base: $opt_prefix
+ library directory: $opt_libdir
+ use system includes: $opt_sysinc_seccomp
+EOF
+}
+
+function msg_error() {
+ echo "error: $@"
+}
+
+function cnf_mk_header() {
+ echo "# generated by configure on $(date -R)" >> $cnf_mk_file
+ echo "# options: \"$opt_str\"" >> $cnf_mk_file
+ echo "" >> $cnf_mk_file
+}
+
+function cnf_mk_footer() {
+ echo "" >> $cnf_mk_file
+}
+
+function cnf_mk_entry() {
+ [[ $# -ne 2 ]] && return
+ case "$2" in
+ no)
+ echo "$1 = 0" >> $cnf_mk_file
+ ;;
+ yes)
+ echo "$1 = 1" >> $cnf_mk_file
+ ;;
+ *)
+ echo "$1 = \"$2\"" >> $cnf_mk_file
+ esac
+}
+
+function cnf_h_header() {
+ echo "/* generated by configure on $(date -R) */" >> $cnf_h_file
+ echo "/* options: \"$opt_str\" */" >> $cnf_h_file
+ echo "" >> $cnf_h_file
+ echo "#ifndef _CONFIGURE_H" >> $cnf_h_file
+ echo "#define _CONFIGURE_H" >> $cnf_h_file
+ echo "" >> $cnf_h_file
+}
+
+function cnf_h_footer() {
+ echo "" >> $cnf_h_file
+ echo "#endif" >> $cnf_h_file
+ echo "" >> $cnf_h_file
+}
+
+function cnf_h_entry() {
+ [[ $# -ne 2 ]] && return
+ case "$2" in
+ no)
+ echo "#undef $1" >> $cnf_h_file
+ ;;
+ yes)
+ echo "#define $1 1" >> $cnf_h_file
+ ;;
+ *)
+ echo "#define $1 $2" >> $cnf_h_file
+ esac
+}
+
+function cnf_reset() {
+ cat /dev/null > $cnf_mk_file
+ cat /dev/null > $cnf_h_file
+}
+
+function cnf_header() {
+ cnf_mk_header
+ cnf_h_header
+}
+
+function cnf_entry() {
+ cnf_mk_entry "$1" "$2"
+ cnf_h_entry "$1" "$2"
+}
+
+function cnf_footer() {
+ cnf_mk_footer
+ cnf_h_footer
+}
+
+function tmpl_filter() {
+ name="echo \$$1"
+ val="$(eval $name)"
+ cat - | sed -e 's/%%'"$1"'%%/'"${val//\//\\/}"'/g;'
+}
+
+####
+# main
+
+#
+# setup
+#
+
+# verify script dependencies
+verify_deps getopt
+
+# parse the command line options
+opt_str="$@"
+opt=$(getopt -n "$0" --options "h" --longoptions "help,prefix:,libdir:" -- "$@")
+eval set -- "$opt"
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --prefix)
+ opt_prefix="$2"
+ shift 2
+ ;;
+ --libdir)
+ opt_libdir="$2"
+ shift 2
+ ;;
+ -h|--help)
+ msg_usage
+ exit 0
+ ;;
+ --)
+ shift
+ ;;
+ *)
+ msg_usage
+ exit 1
+ esac
+done
+
+#
+# validate the command line options
+#
+
+if [[ -e "$opt_prefix" && ! -d "$opt_prefix" ]]; then
+ msg_error "install prefix ($opt_prefix) is not a directory"
+ exit 1
+fi
+
+if [[ -z $opt_libdir ]]; then
+ opt_libdir="$opt_prefix/lib"
+fi
+if [[ -e "$opt_libdir" && ! -d "$opt_libdir" ]]; then
+ msg_error "libdir ($opt_libdir) is not a directory"
+ exit 1
+fi
+
+if [[ "$opt_bindings_python" = "yes" ]]; then
+ if ! test_deps cython; then
+ msg_error "python bindings require the cython package"
+ exit 1
+ fi
+ cython_ver=$(cython -V 2>&1 | cut -d' ' -f 3)
+ if [[ $(echo $cython_ver | cut -d'.' -f 1) -lt 1 &&
+ $(echo $cython_ver | cut -d'.' -f 2) -lt 16 ]]; then
+ msg_error "python bindings require cython 0.16 or higher"
+ exit 1
+ fi
+fi
+
+#
+# automatic configuration
+#
+
+# system seccomp includes
+if [[ -r "/usr/include/linux/seccomp.h" ]]; then
+ opt_sysinc_seccomp="yes"
+else
+ opt_sysinc_seccomp="no"
+fi
+
+# generate the version files
+. ./version_info
+VERSION_RELEASE="${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_MICRO}"
+rm -f ./version_info.mk
+echo "# generated by configure on $(date -R)" >> ./version_info.mk
+echo "VERSION_MAJOR=$VERSION_MAJOR" >> ./version_info.mk
+echo "VERSION_MINOR=$VERSION_MINOR" >> ./version_info.mk
+echo "VERSION_MICRO=$VERSION_MICRO" >> ./version_info.mk
+echo "VERSION_RELEASE=$VERSION_RELEASE" >> ./version_info.mk
+
+# generate the pkg-config metadata
+INSTALL_PREFIX="$opt_prefix"
+INSTALL_LIBDIR="$opt_libdir"
+rm -f ./libseccomp.pc
+cat ./libseccomp.pc.in | \
+ tmpl_filter INSTALL_PREFIX | \
+ tmpl_filter INSTALL_LIBDIR | \
+ tmpl_filter VERSION_RELEASE \
+ >> ./libseccomp.pc
+
+#
+# finish
+#
+
+# reset the configuration files
+cnf_reset
+cnf_header
+
+# output the configuration files
+cnf_mk_entry "CONF_INSTALL_PREFIX" "$opt_prefix"
+cnf_mk_entry "CONF_INSTALL_LIBDIR" "$opt_libdir"
+cnf_entry "CONF_SYSINC_SECCOMP" "$opt_sysinc_seccomp"
+cnf_entry "CONF_BINDINGS_PYTHON" "$opt_bindings_python"
+
+# configuration footer
+cnf_footer
+
+# display a summary and exit
+msg_summary
+exit 0
--- /dev/null
+#
+# Enhanced Seccomp Library Makefile
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+#
+# macros
+#
+
+include ../macros.mk
+
+#
+# configuration
+#
+
+include $(TOPDIR)/version_info.mk
+include $(TOPDIR)/configure.mk
+include $(TOPDIR)/install.mk
+
+MAN1 = \
+ man/man1/scmp_sys_resolver.1
+
+MAN3 = \
+ man/man3/seccomp_init.3 \
+ man/man3/seccomp_load.3 \
+ man/man3/seccomp_release.3 \
+ man/man3/seccomp_reset.3 \
+ man/man3/seccomp_rule_add.3 \
+ man/man3/seccomp_rule_add_exact.3 \
+ man/man3/seccomp_syscall_priority.3 \
+ man/man3/seccomp_syscall_resolve_name.3 \
+ man/man3/seccomp_syscall_resolve_name_arch.3 \
+ man/man3/seccomp_syscall_resolve_num_arch.3 \
+ man/man3/seccomp_export_bpf.3 \
+ man/man3/seccomp_export_pfc.3 \
+ man/man3/seccomp_attr_set.3 \
+ man/man3/seccomp_attr_get.3 \
+ man/man3/seccomp_arch_add.3 \
+ man/man3/seccomp_arch_exist.3 \
+ man/man3/seccomp_arch_native.3 \
+ man/man3/seccomp_arch_remove.3 \
+ man/man3/seccomp_merge.3
+
+#
+# targets
+#
+
+.PHONY: all install install_man1 install_man3
+
+all:
+
+install: install_man1 install_man3
+
+install_man1: $(MAN1)
+ $(INSTALL_MAN1_MACRO)
+
+install_man3: $(MAN3)
+ $(INSTALL_MAN3_MACRO)
--- /dev/null
+.TH "scmp_sys_resolver" 1 "23 May 2013" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+scmp_sys_resolver \- Resolve system calls
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.B scmp_sys_resolver
+[\-h] [\-a
+.I ARCH
+] [\-t]
+.I SYSCALL_NAME
+|
+.I SYSCALL_NUMBER
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+This command resolves both system call names and numbers with respect to the
+given architecture supplied in the optional
+.I ARCH
+argument. If the architecture is not supplied on the command line then the
+native architecture is used. If the "\-t" argument is specified along with a
+system call name, then the system call will be translated as necessary for the
+given architecture. The "\-t" argument has no effect if a system call number
+is specified.
+.P
+In some combinations of architecture and system call, a negative system call
+number will be displayed. A negative system call number indicates that the
+system call is not defined for the given architecture and is treated in a
+special manner by libseccomp depending on the operation.
+.TP
+.B \-a \fIARCH
+The architecture to use for resolving the system call. Valid
+.I ARCH
+values are "x86", "x86_64", "x32", and "arm".
+.TP
+.B \-t
+If neccessary, translate the system call name to the proper system call number,
+even if the system call name is different, e.g. socket(2) on x86.
+.TP
+.B \-h
+A simple one-line usage display.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXIT STATUS
+.\" //////////////////////////////////////////////////////////////////////////
+Returns zero on success, errno values on failure.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This tool, as well as
+the libseccomp library, is currently under development, please report any bugs
+at the project site or directly to the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
--- /dev/null
+.TH "seccomp_arch_add" 3 "26 November 2012" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_arch_add, seccomp_arch_remove, seccomp_arch_exist, seccomp_arch_native \- Manage seccomp filter architectures
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.B typedef void * scmp_filter_ctx;
+.sp
+.B #define SCMP_ARCH_NATIVE
+.B #define SCMP_ARCH_X86
+.B #define SCMP_ARCH_X86_64
+.sp
+.BI "uint32_t seccomp_arch_native();"
+.BI "int seccomp_arch_exist(const scmp_filter_ctx " ctx ", uint32_t " arch_token ");"
+.BI "int seccomp_arch_add(scmp_filter_ctx " ctx ", uint32_t " arch_token ");"
+.BI "int seccomp_arch_remove(scmp_filter_ctx " ctx ", uint32_t " arch_token ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_arch_exist ()
+function tests to see if a given architecture has been added to the seccomp
+filter in
+.I ctx
+, where the
+.BR seccomp_arch_add ()
+and
+.BR seccomp_arch_remove ()
+add and remove, respectively, architectures from the seccomp filter. In all
+three functions, the architecture values given in
+.I arch_token
+should be the
+.BR SCMP_ARCH_*
+defined constants; with the
+.BR SCMP_ARCH_NATIVE
+constant always referring to the native compiled architecture. The
+.BR seccomp_arch_native ()
+function returns the system's architecture such that it will match one of the
+.BR SCMP_ARCH_*
+constants.
+.P
+When a seccomp filter is initialized with the call to
+.BR seccomp_init (3)
+the native architecture is automatically added to the filter. If you want to
+remove the native architecture from the filter, you first need to add another
+architecture to the filter as a seccomp filter must contain at least one
+architecture at all times. After you have added a second architecture to the
+seccomp filter, you can remove the native architecture.
+.P
+When adding a new architecture to an existing filter, the existing rules will
+not be added to the new architecture. However, rules added after adding the
+new architecture will be added to all of the architectures in the filter.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+The
+.BR seccomp_arch_add ()
+and
+.BR seccomp_arch_remove ()
+functions return zero on success, negative errno values on failure. The
+.BR seccomp_arch_exist ()
+function returns zero if the architecture exists, \-EEXIST if it does not, and
+other negative errno values on failure.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc = \-1;
+ scmp_filter_ctx ctx;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ if (seccomp_arch_exist(ctx, SCMP_ARCH_X86) == \-EEXIST) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
+ if (rc != 0)
+ goto out_all;
+ rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE);
+ if (rc != 0)
+ goto out_all;
+ }
+
+ /* ... */
+
+out:
+ seccomp_release(ctx);
+ return \-rc;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_init (3),
+.BR seccomp_reset (3),
+.BR seccom_merge (3)
--- /dev/null
+.so man3/seccomp_arch_add.3
--- /dev/null
+.so man3/seccomp_arch_add.3
--- /dev/null
+.so man3/seccomp_arch_add.3
--- /dev/null
+.so man3/seccomp_attr_set.3
--- /dev/null
+.TH "seccomp_attr_set" 3 "25 July 2012" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_attr_set, seccomp_attr_get \- Manage the seccomp filter attributes
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.B typedef void * scmp_filter_ctx;
+.B enum scmp_filter_attr;
+.sp
+.BI "int seccomp_attr_set(scmp_filter_ctx " ctx ","
+.BI " enum scmp_filter_attr " attr ", uint32_t " value ");"
+.BI "int seccomp_attr_get(scmp_filter_ctx " ctx ","
+.BI " enum scmp_filter_attr " attr ", uint32_t *" value ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_attr_set ()
+function sets the different seccomp filter attributes while the
+.BR seccomp_attr_get ()
+function fetches the filter attributes. The seccomp filter attributes are
+tunable values that affect how the library behaves when generating and loading
+the seccomp filter into the kernel. The attributes are reset to their default
+values whenever the filter is initialized or reset via
+.BR seccomp_filter_init (3)
+or
+.BR seccomp_filter_reset (3).
+.P
+The filter context
+.I ctx
+is the value returned by the call to
+.BR seccomp_init (3).
+.P
+Valid
+.I attr
+values are as follows:
+.TP
+.B SCMP_FLTATR_ACT_DEFAULT
+The default filter action as specified in the call to
+.BR seccomp_filter_init (3)
+or
+.BR seccomp_filter_reset (3).
+This attribute is read-only.
+.TP
+.B SCMP_FLTATR_ACT_BADARCH
+The filter action taken when the loaded filter does not match the architecture
+of the executing application. Defaults to the
+.B SCMP_ACT_KILL
+action.
+.TP
+.B SCMP_FLTATR_CTL_NNP
+A flag to specify if the NO_NEW_PRIVS functionality should be enabled before
+loading the seccomp filter into the kernel. If set to off (
+.I value
+== 0) then loading the seccomp filter into the kernel will fail if CAP_SYS_ADMIN
+is not set. Defaults to on (
+.I value
+== 1).
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+Returns zero on success, negative errno values on failure.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc = \-1;
+ scmp_filter_ctx ctx;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ goto out;
+
+ /* ... */
+
+ rc = seccomp_attr_set(ctx, SCMP_FLTATR_ACT_BADARCH, SCMP_ACT_TRAP);
+ if (rc < 0)
+ goto out;
+
+ /* ... */
+
+out:
+ seccomp_release(ctx);
+ return \-rc;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_init (3),
+.BR seccomp_reset (3),
+.BR seccomp_load (3)
--- /dev/null
+.TH "seccomp_export_bpf" 3 "25 July 2012" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_export_bpf, seccomp_export_pfc \- Export the seccomp filter
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.B typedef void * scmp_filter_ctx;
+.sp
+.BI "int seccomp_export_bpf(const scmp_filter_ctx " ctx ", int " fd ");"
+.BI "int seccomp_export_pfc(const scmp_filter_ctx " ctx ", int " fd ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_export_bpf ()
+and
+.BR seccomp_export_pfc ()
+functions generate and output the current seccomp filter in either BPF (Berkley
+Packet Filter) or PFC (Pseudo Filter Code). The output of
+.BR seccomp_export_bpf ()
+is suitable for loading into the kernel, while the output of
+.BR seccomp_export_pfc ()
+is human readable and is intended primarily as a debugging tool for developers
+using libseccomp. Both functions write the filter to the
+.I fd
+file descriptor.
+.P
+The filter context
+.I ctx
+is the value returned by the call to
+.BR seccomp_init (3).
+.P
+While the two output formats are guaranteed to be functionally equivalent for
+the given seccomp filter configuration, the filter instructions, and their
+ordering, are not guaranteed to be the same in both the BPF and PFC formats.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+Returns zero on success, negative errno values on failure.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc = \-1;
+ scmp_filter_ctx ctx;
+ int filter_fd;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* ... */
+
+ filter_fd = open("/tmp/seccomp_filter.bpf", O_WRONLY);
+ if (filter_fd == \-1) {
+ rc = \-errno;
+ goto out;
+ }
+
+ rc = seccomp_export_bpf(ctx, filter_fd);
+ if (rc < 0) {
+ close(filter_fd);
+ goto out;
+ }
+ close(filter_fd);
+
+ /* ... */
+
+out:
+ seccomp_release(ctx);
+ return \-rc;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_init (3),
+.BR seccomp_release (3)
+
--- /dev/null
+.so man3/seccomp_export_bpf.3
--- /dev/null
+.TH "seccomp_init" 3 "25 July 2012" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_init, seccomp_reset \- Initialize the seccomp filter state
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.B typedef void * scmp_filter_ctx;
+.sp
+.BI "scmp_filter_ctx seccomp_init(uint32_t " def_action ");"
+.BI "int seccomp_reset(scmp_filter_ctx " ctx ", uint32_t " def_action ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_init ()
+and
+.BR seccomp_reset ()
+functions (re)initialize the internal seccomp filter state, prepares it for
+use, and sets the default action based on the
+.I def_action
+parameter. The
+.BR seccomp_init ()
+function must be called before any other libseccomp functions as the rest
+of the library API will fail if the filter context is not initialized properly.
+The
+.BR seccomp_reset ()
+function releases the existing filter context state before reinitializing it
+and can only be called after a call to
+.BR seccomp_init ()
+has succeeded.
+.P
+When the caller is finished configuring the seccomp filter and has loaded it
+into the kernel, the caller should call
+.BR seccomp_release (3)
+to release all of the filter context state.
+.P
+Valid
+.I def_action
+values are as follows:
+.TP
+.B SCMP_ACT_KILL
+The process will be killed by the kernel when it calls a syscall that does not
+match any of the configured seccomp filter rules.
+.TP
+.B SCMP_ACT_TRAP
+The process will throw a SIGSYS signal when it calls a syscall that does not
+match any of the configured seccomp filter rules.
+.TP
+.B SCMP_ACT_ERRNO(uint16_t errno)
+The process will receive a return value of
+.I errno
+when it calls a syscall that does not match any of the configured seccomp filter
+rules.
+.TP
+.B SCMP_ACT_TRACE(uint16_t msg_num)
+If the process is being traced and the tracing process specified the
+.B PTRACE_O_TRACESECCOMP
+option in the call to
+.BR ptrace (2),
+the tracing process will be notified, via
+.B PTRACE_EVENT_SECCOMP
+, and the value provided in
+.I msg_num
+can be retrieved using the
+.B PTRACE_GETEVENTMSG
+option.
+.TP
+.B SCMP_ACT_ALLOW
+The seccomp filter will have no effect on the process calling the syscall if it
+does not match any of the configured seccomp filter rules.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+The
+.BR seccomp_init ()
+function returns a filter context on success, NULL on failure. The
+.BR seccomp_reset ()
+function returns zero on success, negative errno values on failure.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc = \-1;
+ scmp_filter_ctx ctx;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* ... */
+
+ rc = seccomp_reset(ctx, SCMP_ACT_KILL);
+ if (rc < 0)
+ goto out;
+
+ /* ... */
+
+out:
+ seccomp_release(ctx);
+ return \-rc;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_release (3)
+
--- /dev/null
+.TH "seccomp_load" 3 "25 July 2012" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_load \- Load the current seccomp filter into the kernel
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.B typedef void * scmp_filter_ctx;
+.sp
+.BI "int seccomp_load(scmp_filter_ctx " ctx ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+Loads the seccomp filter provided by
+.I ctx
+into the kernel; if the function
+succeeds the new seccomp filter will be active when the function returns.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+Returns zero on success, negative errno values on failure.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc = \-1;
+ scmp_filter_ctx ctx;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* ... */
+
+ rc = seccomp_load(ctx);
+ if (rc < 0)
+ goto out;
+
+ /* ... */
+
+out:
+ seccomp_release(ctx);
+ return \-rc;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_init (3),
+.BR seccomp_reset (3),
+.BR seccomp_release (3),
+.BR seccomp_rule_add (3),
+.BR seccomp_rule_add_exact (3)
+
+
--- /dev/null
+.TH "seccomp_merge" 3 "28 September 2012" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_merge \- Merge two seccomp filters
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.B typedef void * scmp_filter_ctx;
+.sp
+.BI "int seccomp_merge(scmp_filter_ctx " dst ", scmp_filter_ctx " src ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_merge ()
+function merges the seccomp filter in
+.I src
+with the filter in
+.I dst
+and stores the resulting in the
+.I dst
+filter. If successfull, the
+.I src
+seccomp filter is released and all internal memory assocated with the filter
+is freed; there is no need to call
+.BR seccomp_release (3)
+on
+.I src
+and the caller should discard any references to the filter.
+.P
+In order to merge two seccomp filters, both filters must have the same
+attribute values and no overlapping architectures.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+Returns zero on success and negative values on failure.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc = \-1;
+ scmp_filter_ctx ctx_32, ctx_64;
+
+ ctx_32 = seccomp_init(SCMP_ACT_KILL);
+ if (ctx_32 == NULL)
+ goto out_all;
+ ctx_64 = seccomp_init(SCMP_ACT_KILL);
+ if (ctx_64 == NULL)
+ goto out_all;
+
+ if (seccomp_arch_exist(ctx_32, SCMP_ARCH_X86) == \-EEXIST) {
+ rc = seccomp_arch_add(ctx_32, SCMP_ARCH_X86);
+ if (rc != 0)
+ goto out_all;
+ rc = seccomp_arch_remove(ctx_32, SCMP_ARCH_NATIVE);
+ if (rc != 0)
+ goto out_all;
+ }
+ if (seccomp_arch_exist(ctx_64, SCMP_ARCH_X86_64) == \-EEXIST) {
+ rc = seccomp_arch_add(ctx_64, SCMP_ARCH_X86_64);
+ if (rc != 0)
+ goto out_all;
+ rc = seccomp_arch_remove(ctx_64, SCMP_ARCH_NATIVE);
+ if (rc != 0)
+ goto out_all;
+ }
+
+ /* ... */
+
+ rc = seccomp_merge(ctx_64, ctx_32);
+ if (rc != 0)
+ goto out_all;
+
+ /* NOTE: the 'ctx_32' filter is no longer valid at this point */
+
+ /* ... */
+
+out:
+ seccomp_release(ctx_64);
+ return \-rc;
+out_all:
+ seccomp_release(ctx_32);
+ goto out;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_init (3),
+.BR seccomp_reset (3),
+.BR seccomp_arch_add (3),
+.BR seccomp_arch_remove (3),
+.BR seccomp_attr_get (3),
+.BR seccomp_attr_set (3)
--- /dev/null
+.TH "seccomp_release" 3 "25 July 2012" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_release \- Release the seccomp filter state
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.B typedef void * scmp_filter_ctx;
+.sp
+.BI "void seccomp_release(scmp_filter_ctx " ctx ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+Releases the seccomp filter in
+.I ctx
+which was first initialized by
+.BR seccomp_init (3)
+or
+.BR seccomp_reset (3)
+and frees any memory associated with the given seccomp filter context.
+Any seccomp filters loaded into the kernel are not affected.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+Does not return a value.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ scmp_filter_ctx ctx;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ return \-1;
+
+ /* ... */
+
+ seccomp_release(ctx);
+ return 0;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_init (3),
+.BR seccomp_reset (3)
+
+
--- /dev/null
+.so man3/seccomp_init.3
--- /dev/null
+.TH "seccomp_rule_add" 3 "25 July 2012" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_rule_add, seccomp_rule_add_exact \- Add a seccomp filter rule
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.B typedef void * scmp_filter_ctx;
+.sp
+.BI "int SCMP_SYS(" syscall_name ");"
+.sp
+.BI "struct scmp_arg_cmp SCMP_CMP(unsigned int " arg ","
+.BI " enum scmp_compare " op ", " ... ");"
+.BI "struct scmp_arg_cmp SCMP_A0(enum scmp_compare " op ", " ... ");"
+.BI "struct scmp_arg_cmp SCMP_A1(enum scmp_compare " op ", " ... ");"
+.BI "struct scmp_arg_cmp SCMP_A2(enum scmp_compare " op ", " ... ");"
+.BI "struct scmp_arg_cmp SCMP_A3(enum scmp_compare " op ", " ... ");"
+.BI "struct scmp_arg_cmp SCMP_A4(enum scmp_compare " op ", " ... ");"
+.BI "struct scmp_arg_cmp SCMP_A5(enum scmp_compare " op ", " ... ");"
+.sp
+.BI "int seccomp_rule_add(scmp_filter_ctx " ctx ", uint32_t " action ","
+.BI " int " syscall ", unsigned int " arg_cnt ", " ... ");"
+.BI "int seccomp_rule_add_exact(scmp_filter_ctx " ctx ", uint32_t " action ","
+.BI " int " syscall ", unsigned int " arg_cnt ", " ... ");"
+.sp
+.BI "int seccomp_rule_add_array(scmp_filter_ctx " ctx ","
+.BI " uint32_t " action ", int " syscall ","
+.BI " unsigned int " arg_cnt ","
+.BI " const struct scmp_arg_cmp *"arg_array ");"
+.BI "int seccomp_rule_add_exact_array(scmp_filter_ctx " ctx ","
+.BI " uint32_t " action ", int " syscall ","
+.BI " unsigned int " arg_cnt ","
+.BI " const struct scmp_arg_cmp *"arg_array ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_rule_add (),
+.BR seccomp_rule_add_array (),
+.BR seccomp_rule_add_exact (),
+and
+.BR seccomp_rule_add_exact_array ()
+functions all add a new filter rule to the current seccomp filter. The
+.BR seccomp_rule_add ()
+and
+.BR seccomp_rule_add_array ()
+functions will make a "best effort" to add the rule as specified, but may alter
+the rule slightly due to architecture specifics, e.g. socket and ipc functions
+on x86. The
+.BR seccomp_rule_add_exact ()
+and
+.BR seccomp_rule_add_exact_array ()
+functions will attempt to add the rule exactly as specified so it may behave
+differently on different architectures. While it does not guarantee a exact
+filter ruleset,
+.BR seccomp_rule_add ()
+and
+.BR seccomp_rule_add_array ()
+do guarantee the same behavior regardless of the architecture.
+.P
+The newly added filter rule does not take effect until the entire filter is
+loaded into the kernel using
+.BR seccomp_load (3).
+.P
+The
+.BR SCMP_CMP ()
+and
+.BR SCMP_A{0-5} ()
+macros generate a scmp_arg_cmp structure for use with the above functions. The
+.BR SCMP_CMP ()
+macro allows the caller to specify an arbitrary argument along with the
+comparison operator, mask, and datum values where the
+.BR SCMP_A{0-5} ()
+macros are specific to a certain argument. See the EXAMPLES section below.
+.P
+While it is possible to specify the
+.I syscall
+value directly using the standard
+.B __NR_syscall
+values, in order to ensure proper operation across multiple architectures it
+is highly recommended to use the
+.BR SCMP_SYS ()
+macro instead. See the EXAMPLES section below.
+.P
+The filter context
+.I ctx
+is the value returned by the call to
+.BR seccomp_init (3).
+.P
+Valid
+.I action
+values are as follows:
+.TP
+.B SCMP_ACT_KILL
+The process will be killed by the kernel when it calls a syscall that does not
+match any of the configured seccomp filter rules.
+.TP
+.B SCMP_ACT_TRAP
+The process will throw a SIGSYS signal when it calls a syscall that does not
+match any of the configured seccomp filter rules.
+.TP
+.B SCMP_ACT_ERRNO(uint16_t errno)
+The process will receive a return value of
+.I errno
+when it calls a syscall that does not match any of the configured seccomp filter
+rules.
+.TP
+.B SCMP_ACT_TRACE(uint16_t msg_num)
+If the process is being traced and the tracing process specified the
+.B PTRACE_O_TRACESECCOMP
+option in the call to
+.BR ptrace (2),
+the tracing process will be notified, via
+.B PTRACE_EVENT_SECCOMP
+, and the value provided in
+.I msg_num
+can be retrieved using the
+.B PTRACE_GETEVENTMSG
+option.
+.TP
+.B SCMP_ACT_ALLOW
+The seccomp filter will have no effect on the process calling the syscall if it
+does not match any of the configured seccomp filter rules.
+.P
+Valid comparison
+.I op
+values are as follows:
+.TP
+.B SCMP_CMP_NE
+Matches when the argument value is not equal to the datum value, example:
+.sp
+SCMP_CMP(
+.I arg
+, SCMP_CMP_NE ,
+.I datum
+)
+.TP
+.B SCMP_CMP_LT
+Matches when the argument value is less than the datum value, example:
+.sp
+SCMP_CMP(
+.I arg
+, SCMP_CMP_LT ,
+.I datum
+)
+.TP
+.B SCMP_CMP_LE
+Matches when the argument value is less than or equal to the datum value,
+example:
+.sp
+SCMP_CMP(
+.I arg
+, SCMP_CMP_LE ,
+.I datum
+)
+.TP
+.B SCMP_CMP_EQ
+Matches when the argument value is equal to the datum value, example:
+.sp
+SCMP_CMP(
+.I arg
+, SCMP_CMP_EQ ,
+.I datum
+)
+.TP
+.B SCMP_CMP_GE
+Matches when the argument value is greater than or equal to the datum value,
+example:
+.sp
+SCMP_CMP(
+.I arg
+, SCMP_CMP_GE ,
+.I datum
+)
+.TP
+.B SCMP_CMP_GT
+Matches when the argument value is greater than the datum value, example:
+.sp
+SCMP_CMP(
+.I arg
+, SCMP_CMP_GT ,
+.I datum
+)
+.TP
+.B SCMP_CMP_MASKED_EQ
+Matches when the masked argument value is equal to the masked datum value,
+example:
+.sp
+SCMP_CMP(
+.I arg
+, SCMP_CMP_MASKED_EQ ,
+.I mask
+,
+.I datum
+)
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+The
+.BR seccomp_rule_add (),
+.BR seccomp_rule_add_array (),
+.BR seccomp_rule_add_exact (),
+and
+.BR seccomp_rule_add_exact_array ()
+functions return zero on success, negative errno values on failure.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <fcntl.h>
+#include <seccomp.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#define BUF_SIZE 256
+
+int main(int argc, char *argv[])
+{
+ int rc = \-1;
+ scmp_filter_ctx ctx;
+ struct scmp_arg_cmp arg_cmp[] = { SCMP_A0(SCMP_CMP_EQ, 2) };
+ int fd;
+ unsigned char buf[BUF_SIZE];
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* ... */
+
+ fd = open("file.txt", 0);
+
+ /* ... */
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc < 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 3,
+ SCMP_A0(SCMP_CMP_EQ, fd),
+ SCMP_A1(SCMP_CMP_EQ, (scmp_datum_t)buf),
+ SCMP_A2(SCMP_CMP_LE, BUF_SIZE));
+ if (rc < 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_CMP(0, SCMP_CMP_EQ, fd));
+ if (rc < 0)
+ goto out;
+
+ rc = seccomp_rule_add_array(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ arg_cmp);
+ if (rc < 0)
+ goto out;
+
+ rc = seccomp_load(ctx);
+ if (rc < 0)
+ goto out;
+
+ /* ... */
+
+out:
+ seccomp_release(ctx);
+ return \-rc;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_syscall_priority (3),
+.BR seccomp_load (3)
--- /dev/null
+.so man3/seccomp_rule_add.3
--- /dev/null
+.so man3/seccomp_rule_add.3
--- /dev/null
+.so man3/seccomp_rule_add.3
--- /dev/null
+.TH "seccomp_syscall_priority" 3 "25 July 2012" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_syscall_priority \- Prioritize syscalls in the seccomp filter
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.B typedef void * scmp_filter_ctx;
+.sp
+.BI "int SCMP_SYS(" syscall_name ");"
+.sp
+.BI "int seccomp_syscall_priority(scmp_filter_ctx " ctx ","
+.BI " int " syscall ", uint8_t " priority ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_syscall_priority ()
+function provides a priority hint to the seccomp filter generator in libseccomp
+such that higher priority syscalls are placed earlier in the seccomp filter code
+so that they incur less overhead at the expense of lower priority syscalls. A
+syscall's priority can be set regardless of if any rules currently exist for
+that syscall; the library will remember the priority and it will be assigned to
+the syscall if and when a rule for that syscall is created.
+.P
+While it is possible to specify the
+.I syscall
+value directly using the standard
+.B __NR_syscall
+values, in order to ensure proper operation across multiple architectures it
+is highly recommended to use the
+.BR SCMP_SYS ()
+macro instead. See the EXAMPLES section below.
+.P
+The
+.I priority
+parameter takes an 8-bit value ranging from 0 \- 255; a higher value represents
+a higher priority.
+.P
+The filter context
+.I ctx
+is the value returned by the call to
+.BR seccomp_init ().
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+The
+.BR seccomp_syscall_priority ()
+function returns zero on success, negative errno values on failure. The
+.BR SCMP_SYS ()
+macro returns a value suitable for use as the
+.I syscall
+value in
+.BR seccomp_syscall_priority ().
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc = \-1;
+ scmp_filter_ctx ctx;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* ... */
+
+ rc = seccomp_syscall_priority(ctx, SCMP_SYS(read), 200);
+ if (rc < 0)
+ goto out;
+
+ /* ... */
+
+out:
+ seccomp_release(ctx);
+ return \-rc;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_rule_add (3),
+.BR seccomp_rule_add_exact (3)
--- /dev/null
+.TH "seccomp_syscall_resolve_name" 3 "7 January 2013" "paul@paul-moore.com" "libseccomp Documentation"
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NAME
+.\" //////////////////////////////////////////////////////////////////////////
+seccomp_syscall_resolve_name \- Resolve a syscall name
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SYNOPSIS
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+.B #include <seccomp.h>
+.sp
+.BI "int seccomp_syscall_resolve_name(const char *" name ");"
+.BI "int seccomp_syscall_resolve_name_arch(uint32_t " arch_token ","
+.BI " const char *" name ");"
+.BI "char *seccomp_syscall_resolve_num_arch(uint32_t " arch_token ", int " num ");"
+.sp
+Link with \fI\-lseccomp\fP.
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH DESCRIPTION
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+The
+.BR seccomp_syscall_resolve_name ()
+and
+.BR seccomp_syscall_resolve_name_arch()
+functions resolve the commonly used syscall name to the syscall number used by
+the kernel and the rest of the libseccomp API. The
+.BR seccomp_syscall_resolve_num_arch()
+function resolves the syscall number used by the kernel to the commonly used
+syscall name.
+.P
+The caller is responsible for freeing the returned string from
+.BR seccomp_syscall_resolve_num_arch() .
+.\" //////////////////////////////////////////////////////////////////////////
+.SH RETURN VALUE
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+In the case of
+.BR seccomp_syscall_resolve_name ()
+and
+.BR seccomp_syscall_resolve_name_arch()
+the associated syscall number is returned, with the negative pseudo syscall
+number being returned in cases where the given syscall does not exist for the
+architeture. The value
+.BR __NR_SCMP_ERROR
+is returned in case of error. In all cases, the return value is suitable for
+use in any libseccomp API function which requires the syscall number, examples include
+.BR seccomp_rule_add ()
+and
+.BR seccomp_rule_add_exact ().
+.P
+In the case of
+.BR seccomp_syscall_resolve_num_arch()
+the associated syscall name is returned and it remains the callers
+responsibility to free the returned string via
+.BR free (3).
+.\" //////////////////////////////////////////////////////////////////////////
+.SH EXAMPLES
+.\" //////////////////////////////////////////////////////////////////////////
+.nf
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc = \-1;
+ scmp_filter_ctx ctx;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* ... */
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW,
+ seccomp_syscall_resolve_name("open"), 0);
+ if (rc < 0)
+ goto out;
+
+ /* ... */
+
+ rc = seccomp_load(ctx);
+ if (rc < 0)
+ goto out;
+
+ /* ... */
+
+out:
+ seccomp_release(ctx);
+ return \-rc;
+}
+.fi
+.\" //////////////////////////////////////////////////////////////////////////
+.SH NOTES
+.\" //////////////////////////////////////////////////////////////////////////
+.P
+While the seccomp filter can be generated independent of the kernel, kernel
+support is required to load and enforce the seccomp filter generated by
+libseccomp.
+.P
+The libseccomp project site, with more information and the source code
+repository, can be found at http://libseccomp.sf.net. This library is currently
+under development, please report any bugs at the project site or directly to
+the author.
+.\" //////////////////////////////////////////////////////////////////////////
+.SH AUTHOR
+.\" //////////////////////////////////////////////////////////////////////////
+Paul Moore <paul@paul-moore.com>
+.\" //////////////////////////////////////////////////////////////////////////
+.SH SEE ALSO
+.\" //////////////////////////////////////////////////////////////////////////
+.BR seccomp_rule_add (3),
+.BR seccomp_rule_add_exact (3)
--- /dev/null
+.so man3/seccomp_syscall_resolve_name.3
--- /dev/null
+.so man3/seccomp_syscall_resolve_name.3
--- /dev/null
+#
+# Enhanced Seccomp Library Makefile
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+#
+# macros
+#
+
+include ../macros.mk
+
+#
+# configuration
+#
+
+include $(TOPDIR)/version_info.mk
+include $(TOPDIR)/configure.mk
+include $(TOPDIR)/install.mk
+
+HDR_BUILD = seccomp.h
+
+#
+# targets
+#
+
+.PHONY: all install clean
+
+all: $(HDR_BUILD)
+
+install: $(HDR_BUILD)
+ $(INSTALL_INC_MACRO)
+
+seccomp.h: seccomp.h.in
+ @$(ECHO) " GEN $@"
+ $(CAT) $< | \
+ $(SED) -e 's/%%VERSION_MAJOR%%/$(VERSION_MAJOR)/g' | \
+ $(SED) -e 's/%%VERSION_MINOR%%/$(VERSION_MINOR)/g' | \
+ $(SED) -e 's/%%VERSION_MICRO%%/$(VERSION_MICRO)/g' > $@
+
+clean:
+ @$(RM) $(HDR_BUILD)
--- /dev/null
+/**
+ * Seccomp Library
+ *
+ * Copyright (c) 2012,2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _SECCOMP_H
+#define _SECCOMP_H
+
+#include <elf.h>
+#include <inttypes.h>
+#include <asm/unistd.h>
+#include <linux/audit.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * version information
+ */
+
+#define SCMP_VER_MAJOR %%VERSION_MAJOR%%
+#define SCMP_VER_MINOR %%VERSION_MINOR%%
+#define SCMP_VER_MICRO %%VERSION_MICRO%%
+
+/*
+ * types
+ */
+
+/**
+ * Filter context/handle
+ */
+typedef void *scmp_filter_ctx;
+
+/**
+ * Filter attributes
+ */
+enum scmp_filter_attr {
+ _SCMP_FLTATR_MIN = 0,
+ SCMP_FLTATR_ACT_DEFAULT = 1, /**< default filter action */
+ SCMP_FLTATR_ACT_BADARCH = 2, /**< bad architecture action */
+ SCMP_FLTATR_CTL_NNP = 3, /**< set NO_NEW_PRIVS on filter load */
+ _SCMP_FLTATR_MAX,
+};
+
+/**
+ * Comparison operators
+ */
+enum scmp_compare {
+ _SCMP_CMP_MIN = 0,
+ SCMP_CMP_NE = 1, /**< not equal */
+ SCMP_CMP_LT = 2, /**< less than */
+ SCMP_CMP_LE = 3, /**< less than or equal */
+ SCMP_CMP_EQ = 4, /**< equal */
+ SCMP_CMP_GE = 5, /**< greater than or equal */
+ SCMP_CMP_GT = 6, /**< greater than */
+ SCMP_CMP_MASKED_EQ = 7, /**< masked equality */
+ _SCMP_CMP_MAX,
+};
+
+/**
+ * Argument datum
+ */
+typedef uint64_t scmp_datum_t;
+
+/**
+ * Argument / Value comparison definition
+ */
+struct scmp_arg_cmp {
+ unsigned int arg; /**< argument number, starting at 0 */
+ enum scmp_compare op; /**< the comparison op, e.g. SCMP_CMP_* */
+ scmp_datum_t datum_a;
+ scmp_datum_t datum_b;
+};
+
+/*
+ * macros/defines
+ */
+
+/**
+ * The native architecture token
+ */
+#define SCMP_ARCH_NATIVE 0
+
+/**
+ * The x86 (32-bit) architecture token
+ */
+#define SCMP_ARCH_X86 AUDIT_ARCH_I386
+
+/**
+ * The x86-64 (64-bit) architecture token
+ */
+#define SCMP_ARCH_X86_64 AUDIT_ARCH_X86_64
+
+/**
+ * The x32 (32-bit x86_64) architecture token
+ *
+ * NOTE: this is different from the value used by the kernel because we need to
+ * be able to distinguish between x32 and x86_64
+ */
+#define SCMP_ARCH_X32 (EM_X86_64|__AUDIT_ARCH_LE)
+
+/**
+ * The ARM architecture token
+ */
+#define SCMP_ARCH_ARM AUDIT_ARCH_ARM
+
+/**
+ * Convert a syscall name into the associated syscall number
+ * @param x the syscall name
+ */
+#define SCMP_SYS(x) (__NR_##x)
+
+/**
+ * Specify an argument comparison struct for use in declaring rules
+ * @param arg the argument number, starting at 0
+ * @param op the comparison operator, e.g. SCMP_CMP_*
+ * @param datum_a dependent on comparison
+ * @param datum_b dependent on comparison, optional
+ */
+#define SCMP_CMP(...) ((struct scmp_arg_cmp){__VA_ARGS__})
+
+/**
+ * Specify an argument comparison struct for argument 0
+ */
+#define SCMP_A0(...) SCMP_CMP(0, __VA_ARGS__)
+
+/**
+ * Specify an argument comparison struct for argument 1
+ */
+#define SCMP_A1(...) SCMP_CMP(1, __VA_ARGS__)
+
+/**
+ * Specify an argument comparison struct for argument 2
+ */
+#define SCMP_A2(...) SCMP_CMP(2, __VA_ARGS__)
+
+/**
+ * Specify an argument comparison struct for argument 3
+ */
+#define SCMP_A3(...) SCMP_CMP(3, __VA_ARGS__)
+
+/**
+ * Specify an argument comparison struct for argument 4
+ */
+#define SCMP_A4(...) SCMP_CMP(4, __VA_ARGS__)
+
+/**
+ * Specify an argument comparison struct for argument 5
+ */
+#define SCMP_A5(...) SCMP_CMP(5, __VA_ARGS__)
+
+/*
+ * seccomp actions
+ */
+
+/**
+ * Kill the process
+ */
+#define SCMP_ACT_KILL 0x00000000U
+/**
+ * Throw a SIGSYS signal
+ */
+#define SCMP_ACT_TRAP 0x00030000U
+/**
+ * Return the specified error code
+ */
+#define SCMP_ACT_ERRNO(x) (0x00050000U | ((x) & 0x0000ffffU))
+/**
+ * Notify a tracing process with the specified value
+ */
+#define SCMP_ACT_TRACE(x) (0x7ff00000U | ((x) & 0x0000ffffU))
+/**
+ * Allow the syscall to be executed
+ */
+#define SCMP_ACT_ALLOW 0x7fff0000U
+
+/*
+ * functions
+ */
+
+/**
+ * Initialize the filter state
+ * @param def_action the default filter action
+ *
+ * This function initializes the internal seccomp filter state and should
+ * be called before any other functions in this library to ensure the filter
+ * state is initialized. Returns a filter context on success, NULL on failure.
+ *
+ */
+scmp_filter_ctx seccomp_init(uint32_t def_action);
+
+/**
+ * Reset the filter state
+ * @param ctx the filter context
+ * @param def_action the default filter action
+ *
+ * This function resets the given seccomp filter state and ensures the
+ * filter state is reinitialized. This function does not reset any seccomp
+ * filters already loaded into the kernel. Returns zero on success, negative
+ * values on failure.
+ *
+ */
+int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action);
+
+/**
+ * Destroys the filter state and releases any resources
+ * @param ctx the filter context
+ *
+ * This functions destroys the given seccomp filter state and releases any
+ * resources, including memory, associated with the filter state. This
+ * function does not reset any seccomp filters already loaded into the kernel.
+ * The filter context can no longer be used after calling this function.
+ *
+ */
+void seccomp_release(scmp_filter_ctx ctx);
+
+/**
+ * Merge two filters
+ * @param ctx_dst the destination filter context
+ * @param ctx_src the source filter context
+ *
+ * This function merges two filter contexts into a single filter context and
+ * destroys the second filter context. The two filter contexts must have the
+ * same attribute values and not contain any of the same architectures; if they
+ * do, the merge operation will fail. On success, the source filter context
+ * will be destroyed and should no longer be used; it is not necessary to
+ * call seccomp_release() on the source filter context. Returns zero on
+ * success, negative values on failure.
+ *
+ */
+int seccomp_merge(scmp_filter_ctx ctx_dst, scmp_filter_ctx ctx_src);
+
+/**
+ * Return the native architecture token
+ *
+ * This function returns the native architecture token value, e.g. SCMP_ARCH_*.
+ *
+ */
+uint32_t seccomp_arch_native(void);
+
+/**
+ * Check to see if an existing architecture is present in the filter
+ * @param ctx the filter context
+ * @param arch_token the architecture token, e.g. SCMP_ARCH_*
+ *
+ * This function tests to see if a given architecture is included in the filter
+ * context. If the architecture token is SCMP_ARCH_NATIVE then the native
+ * architecture will be assumed. Returns zero if the architecture exists in
+ * the filter, -EEXIST if it is not present, and other negative values on
+ * failure.
+ *
+ */
+int seccomp_arch_exist(const scmp_filter_ctx ctx, uint32_t arch_token);
+
+/**
+ * Adds an architecture to the filter
+ * @param ctx the filter context
+ * @param arch_token the architecture token, e.g. SCMP_ARCH_*
+ *
+ * This function adds a new architecture to the given seccomp filter context.
+ * Any new rules added after this function successfully returns will be added
+ * to this architecture but existing rules will not be added to this
+ * architecture. If the architecture token is SCMP_ARCH_NATIVE then the native
+ * architecture will be assumed. Returns zero on success, negative values on
+ * failure.
+ *
+ */
+int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token);
+
+/**
+ * Removes an architecture from the filter
+ * @param ctx the filter context
+ * @param arch_token the architecture token, e.g. SCMP_ARCH_*
+ *
+ * This function removes an architecture from the given seccomp filter context.
+ * If the architecture token is SCMP_ARCH_NATIVE then the native architecture
+ * will be assumed. Returns zero on success, negative values on failure.
+ *
+ */
+int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token);
+
+/**
+ * Loads the filter into the kernel
+ * @param ctx the filter context
+ *
+ * This function loads the given seccomp filter context into the kernel. If
+ * the filter was loaded correctly, the kernel will be enforcing the filter
+ * when this function returns. Returns zero on success, negative values on
+ * error.
+ *
+ */
+int seccomp_load(const scmp_filter_ctx ctx);
+
+/**
+ * Get the value of a filter attribute
+ * @param ctx the filter context
+ * @param attr the filter attribute name
+ * @param value the filter attribute value
+ *
+ * This function fetches the value of the given attribute name and returns it
+ * via @value. Returns zero on success, negative values on failure.
+ *
+ */
+int seccomp_attr_get(const scmp_filter_ctx ctx,
+ enum scmp_filter_attr attr, uint32_t *value);
+
+/**
+ * Set the value of a filter attribute
+ * @param ctx the filter context
+ * @param attr the filter attribute name
+ * @param value the filter attribute value
+ *
+ * This function sets the value of the given attribute. Returns zero on
+ * success, negative values on failure.
+ *
+ */
+int seccomp_attr_set(scmp_filter_ctx ctx,
+ enum scmp_filter_attr attr, uint32_t value);
+
+/**
+ * Resolve a syscall number to a name
+ * @param arch_token the architecture token, e.g. SCMP_ARCH_*
+ * @param num the syscall number
+ *
+ * Resolve the given syscall number to the syscall name for the given
+ * architecture; it is up to the caller to free the returned string. Returns
+ * the syscall name on success, NULL on failure.
+ *
+ */
+char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num);
+
+/**
+ * Resolve a syscall name to a number
+ * @param arch_token the architecture token, e.g. SCMP_ARCH_*
+ * @param name the syscall name
+ *
+ * Resolve the given syscall name to the syscall number for the given
+ * architecture. Returns the syscall number on success, including negative
+ * pseudo syscall numbers (e.g. __PNR_*); returns __NR_SCMP_ERROR on failure.
+ *
+ */
+int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name);
+
+/**
+ * Resolve a syscall name to a number
+ * @param name the syscall name
+ *
+ * Resolve the given syscall name to the syscall number. Returns the syscall
+ * number on success, including negative pseudo syscall numbers (e.g. __PNR_*);
+ * returns __NR_SCMP_ERROR on failure.
+ *
+ */
+int seccomp_syscall_resolve_name(const char *name);
+
+/**
+ * Set the priority of a given syscall
+ * @param ctx the filter context
+ * @param syscall the syscall number
+ * @param priority priority value, higher value == higher priority
+ *
+ * This function sets the priority of the given syscall; this value is used
+ * when generating the seccomp filter code such that higher priority syscalls
+ * will incur less filter code overhead than the lower priority syscalls in the
+ * filter. Returns zero on success, negative values on failure.
+ *
+ */
+int seccomp_syscall_priority(scmp_filter_ctx ctx,
+ int syscall, uint8_t priority);
+
+/**
+ * Add a new rule to the filter
+ * @param ctx the filter context
+ * @param action the filter action
+ * @param syscall the syscall number
+ * @param arg_cnt the number of argument filters in the argument filter chain
+ * @param ... scmp_arg_cmp structs (use of SCMP_ARG_CMP() recommended)
+ *
+ * This function adds a series of new argument/value checks to the seccomp
+ * filter for the given syscall; multiple argument/value checks can be
+ * specified and they will be chained together (AND'd together) in the filter.
+ * If the specified rule needs to be adjusted due to architecture specifics it
+ * will be adjusted without notification. Returns zero on success, negative
+ * values on failure.
+ *
+ */
+int seccomp_rule_add(scmp_filter_ctx ctx,
+ uint32_t action, int syscall, unsigned int arg_cnt, ...);
+
+
+/**
+ * Add a new rule to the filter
+ * @param ctx the filter context
+ * @param action the filter action
+ * @param syscall the syscall number
+ * @param arg_cnt the number of elements in the arg_array parameter
+ * @param arg_array array of scmp_arg_cmp structs
+ *
+ * This function adds a series of new argument/value checks to the seccomp
+ * filter for the given syscall; multiple argument/value checks can be
+ * specified and they will be chained together (AND'd together) in the filter.
+ * If the specified rule needs to be adjusted due to architecture specifics it
+ * will be adjusted without notification. Returns zero on success, negative
+ * values on failure.
+ *
+ */
+int seccomp_rule_add_array(scmp_filter_ctx ctx,
+ uint32_t action, int syscall, unsigned int arg_cnt,
+ const struct scmp_arg_cmp *arg_array);
+
+/**
+ * Add a new rule to the filter
+ * @param ctx the filter context
+ * @param action the filter action
+ * @param syscall the syscall number
+ * @param arg_cnt the number of argument filters in the argument filter chain
+ * @param ... scmp_arg_cmp structs (use of SCMP_ARG_CMP() recommended)
+ *
+ * This function adds a series of new argument/value checks to the seccomp
+ * filter for the given syscall; multiple argument/value checks can be
+ * specified and they will be chained together (AND'd together) in the filter.
+ * If the specified rule can not be represented on the architecture the
+ * function will fail. Returns zero on success, negative values on failure.
+ *
+ */
+int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action,
+ int syscall, unsigned int arg_cnt, ...);
+
+/**
+ * Add a new rule to the filter
+ * @param ctx the filter context
+ * @param action the filter action
+ * @param syscall the syscall number
+ * @param arg_cnt the number of elements in the arg_array parameter
+ * @param arg_array array of scmp_arg_cmp structs
+ *
+ * This function adds a series of new argument/value checks to the seccomp
+ * filter for the given syscall; multiple argument/value checks can be
+ * specified and they will be chained together (AND'd together) in the filter.
+ * If the specified rule can not be represented on the architecture the
+ * function will fail. Returns zero on success, negative values on failure.
+ *
+ */
+int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,
+ uint32_t action, int syscall,
+ unsigned int arg_cnt,
+ const struct scmp_arg_cmp *arg_array);
+
+/**
+ * Generate seccomp Pseudo Filter Code (PFC) and export it to a file
+ * @param ctx the filter context
+ * @param fd the destination fd
+ *
+ * This function generates seccomp Pseudo Filter Code (PFC) and writes it to
+ * the given fd. Returns zero on success, negative values on failure.
+ *
+ */
+int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd);
+
+/**
+ * Generate seccomp Berkley Packet Filter (BPF) code and export it to a file
+ * @param ctx the filter context
+ * @param fd the destination fd
+ *
+ * This function generates seccomp Berkley Packer Filter (BPF) code and writes
+ * it to the given fd. Returns zero on success, negative values on failure.
+ *
+ */
+int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd);
+
+/*
+ * pseudo syscall definitions
+ */
+
+/* NOTE - pseudo syscall values {-1..-99} are reserved */
+#define __NR_SCMP_ERROR -1
+
+/* socket syscalls */
+
+#define __PNR_socket -101
+#ifndef __NR_socket
+#define __NR_socket __PNR_socket
+#endif /* __NR_socket */
+
+#define __PNR_bind -102
+#ifndef __NR_bind
+#define __NR_bind __PNR_bind
+#endif /* __NR_bind */
+
+#define __PNR_connect -103
+#ifndef __NR_connect
+#define __NR_connect __PNR_connect
+#endif /* __NR_connect */
+
+#define __PNR_listen -104
+#ifndef __NR_listen
+#define __NR_listen __PNR_listen
+#endif /* __NR_listen */
+
+#define __PNR_accept -105
+#ifndef __NR_accept
+#define __NR_accept __PNR_accept
+#endif /* __NR_accept */
+
+#define __PNR_getsockname -106
+#ifndef __NR_getsockname
+#define __NR_getsockname __PNR_getsockname
+#endif /* __NR_getsockname */
+
+#define __PNR_getpeername -107
+#ifndef __NR_getpeername
+#define __NR_getpeername __PNR_getpeername
+#endif /* __NR_getpeername */
+
+#define __PNR_socketpair -108
+#ifndef __NR_socketpair
+#define __NR_socketpair __PNR_socketpair
+#endif /* __NR_socketpair */
+
+#define __PNR_send -109
+#ifndef __NR_send
+#define __NR_send __PNR_send
+#endif /* __NR_send */
+
+#define __PNR_recv -110
+#ifndef __NR_recv
+#define __NR_recv __PNR_recv
+#endif /* __NR_recv */
+
+#define __PNR_sendto -111
+#ifndef __NR_sendto
+#define __NR_sendto __PNR_sendto
+#endif /* __NR_sendto */
+
+#define __PNR_recvfrom -112
+#ifndef __NR_recvfrom
+#define __NR_recvfrom __PNR_recvfrom
+#endif /* __NR_recvfrom */
+
+#define __PNR_shutdown -113
+#ifndef __NR_shutdown
+#define __NR_shutdown __PNR_shutdown
+#endif /* __NR_shutdown */
+
+#define __PNR_setsockopt -114
+#ifndef __NR_setsockopt
+#define __NR_setsockopt __PNR_setsockopt
+#endif /* __NR_getsockopt */
+
+#define __PNR_getsockopt -115
+#ifndef __NR_getsockopt
+#define __NR_getsockopt __PNR_getsockopt
+#endif /* __NR_getsockopt */
+
+#define __PNR_sendmsg -116
+#ifndef __NR_sendmsg
+#define __NR_sendmsg __PNR_sendmsg
+#endif /* __NR_sendmsg */
+
+#define __PNR_recvmsg -117
+#ifndef __NR_recvmsg
+#define __NR_recvmsg __PNR_recvmsg
+#endif /* __NR_recvmsg */
+
+#define __PNR_accept4 -118
+#ifndef __NR_accept4
+#define __NR_accept4 __PNR_accept4
+#endif /* __NR_accept4 */
+
+#define __PNR_recvmmsg -119
+#ifndef __NR_recvmmsg
+#define __NR_recvmmsg __PNR_recvmmsg
+#endif /* __NR_recvmmsg */
+
+#define __PNR_sendmmsg -120
+#ifndef __NR_sendmmsg
+#define __NR_sendmmsg __PNR_sendmmsg
+#endif /* __NR_sendmmsg */
+
+/* ipc syscalls */
+
+#define __PNR_semop -201
+#ifndef __NR_semop
+#define __NR_semop __PNR_semop
+#endif /* __NR_semop */
+
+#define __PNR_semget -202
+#ifndef __NR_semget
+#define __NR_semget __PNR_semget
+#endif /* __NR_semget */
+
+#define __PNR_semctl -203
+#ifndef __NR_semctl
+#define __NR_semctl __PNR_semctl
+#endif /* __NR_semctl */
+
+#define __PNR_semtimedop -204
+#ifndef __NR_semtimedop
+#define __NR_semtimedop __PNR_semtimedop
+#endif /* __NR_semtime */
+
+#define __PNR_msgsnd -211
+#ifndef __NR_msgsnd
+#define __NR_msgsnd __PNR_msgsnd
+#endif /* __NR_msgsnd */
+
+#define __PNR_msgrcv -212
+#ifndef __NR_msgrcv
+#define __NR_msgrcv __PNR_msgrcv
+#endif /* __NR_msgrcv */
+
+#define __PNR_msgget -213
+#ifndef __NR_msgget
+#define __NR_msgget __PNR_msgget
+#endif /* __NR_msgget */
+
+#define __PNR_msgctl -214
+#ifndef __NR_msgctl
+#define __NR_msgctl __PNR_msgctl
+#endif /* __NR_msgctl */
+
+#define __PNR_shmat -221
+#ifndef __NR_shmat
+#define __NR_shmat __PNR_shmat
+#endif /* __NR_shmat */
+
+#define __PNR_shmdt -222
+#ifndef __NR_shmdt
+#define __NR_shmdt __PNR_shmdt
+#endif /* __NR_shmdt */
+
+#define __PNR_shmget -223
+#ifndef __NR_shmget
+#define __NR_shmget __PNR_shmget
+#endif /* __NR_shmget */
+
+#define __PNR_shmctl -224
+#ifndef __NR_shmctl
+#define __NR_shmctl __PNR_shmctl
+#endif /* __NR_shmctl */
+
+/* single syscalls */
+
+#define __PNR_arch_prctl -10001
+#ifndef __NR_arch_prctl
+#define __NR_arch_prctl __PNR_arch_prctl
+#endif /* __NR_arch_prctl */
+
+#define __PNR_bdflush -10002
+#ifndef __NR_bdflush
+#define __NR_bdflush __PNR_bdflush
+#endif /* __NR_bdflush */
+
+#define __PNR_break -10003
+#ifndef __NR_break
+#define __NR_break __PNR_break
+#endif /* __NR_break */
+
+#define __PNR_chown32 -10004
+#ifndef __NR_chown32
+#define __NR_chown32 __PNR_chown32
+#endif /* __NR_chown32 */
+
+#define __PNR_epoll_ctl_old -10005
+#ifndef __NR_epoll_ctl_old
+#define __NR_epoll_ctl_old __PNR_epoll_ctl_old
+#endif /* __NR_epoll_ctl_old */
+
+#define __PNR_epoll_wait_old -10006
+#ifndef __NR_epoll_wait_old
+#define __NR_epoll_wait_old __PNR_epoll_wait_old
+#endif /* __NR_epoll_wait_old */
+
+#define __PNR_fadvise64_64 -10007
+#ifndef __NR_fadvise64_64
+#define __NR_fadvise64_64 __PNR_fadvise64_64
+#endif /* __NR_fadvise64_64 */
+
+#define __PNR_fchown32 -10008
+#ifndef __NR_fchown32
+#define __NR_fchown32 __PNR_fchown32
+#endif /* __NR_fchown32 */
+
+#define __PNR_fcntl64 -10009
+#ifndef __NR_fcntl64
+#define __NR_fcntl64 __PNR_fcntl64
+#endif /* __NR_fcntl64 */
+
+#define __PNR_fstat64 -10010
+#ifndef __NR_fstat64
+#define __NR_fstat64 __PNR_fstat64
+#endif /* __NR_fstat64 */
+
+#define __PNR_fstatat64 -10011
+#ifndef __NR_fstatat64
+#define __NR_fstatat64 __PNR_fstatat64
+#endif /* __NR_fstatat64 */
+
+#define __PNR_fstatfs64 -10012
+#ifndef __NR_fstatfs64
+#define __NR_fstatfs64 __PNR_fstatfs64
+#endif /* __NR_fstatfs64 */
+
+#define __PNR_ftime -10013
+#ifndef __NR_ftime
+#define __NR_ftime __PNR_ftime
+#endif /* __NR_ftime */
+
+#define __PNR_ftruncate64 -10014
+#ifndef __NR_ftruncate64
+#define __NR_ftruncate64 __PNR_ftruncate64
+#endif /* __NR_ftruncate64 */
+
+#define __PNR_getegid32 -10015
+#ifndef __NR_getegid32
+#define __NR_getegid32 __PNR_getegid32
+#endif /* __NR_getegid32 */
+
+#define __PNR_geteuid32 -10016
+#ifndef __NR_geteuid32
+#define __NR_geteuid32 __PNR_geteuid32
+#endif /* __NR_geteuid32 */
+
+#define __PNR_getgid32 -10017
+#ifndef __NR_getgid32
+#define __NR_getgid32 __PNR_getgid32
+#endif /* __NR_getgid32 */
+
+#define __PNR_getgroups32 -10018
+#ifndef __NR_getgroups32
+#define __NR_getgroups32 __PNR_getgroups32
+#endif /* __NR_getgroups32 */
+
+#define __PNR_getresgid32 -10019
+#ifndef __NR_getresgid32
+#define __NR_getresgid32 __PNR_getresgid32
+#endif /* __NR_getresgid32 */
+
+#define __PNR_getresuid32 -10020
+#ifndef __NR_getresuid32
+#define __NR_getresuid32 __PNR_getresuid32
+#endif /* __NR_getresuid32 */
+
+#define __PNR_getuid32 -10021
+#ifndef __NR_getuid32
+#define __NR_getuid32 __PNR_getuid32
+#endif /* __NR_getuid32 */
+
+#define __PNR_gtty -10022
+#ifndef __NR_gtty
+#define __NR_gtty __PNR_gtty
+#endif /* __NR_gtty */
+
+#define __PNR_idle -10023
+#ifndef __NR_idle
+#define __NR_idle __PNR_idle
+#endif /* __NR_idle */
+
+#define __PNR_ipc -10024
+#ifndef __NR_ipc
+#define __NR_ipc __PNR_ipc
+#endif /* __NR_ipc */
+
+#define __PNR_lchown32 -10025
+#ifndef __NR_lchown32
+#define __NR_lchown32 __PNR_lchown32
+#endif /* __NR_lchown32 */
+
+#define __PNR__llseek -10026
+#ifndef __NR__llseek
+#define __NR__llseek __PNR__llseek
+#endif /* __NR__llseek */
+
+#define __PNR_lock -10027
+#ifndef __NR_lock
+#define __NR_lock __PNR_lock
+#endif /* __NR_lock */
+
+#define __PNR_lstat64 -10028
+#ifndef __NR_lstat64
+#define __NR_lstat64 __PNR_lstat64
+#endif /* __NR_lstat64 */
+
+#define __PNR_mmap2 -10029
+#ifndef __NR_mmap2
+#define __NR_mmap2 __PNR_mmap2
+#endif /* __NR_mmap2 */
+
+#define __PNR_mpx -10030
+#ifndef __NR_mpx
+#define __NR_mpx __PNR_mpx
+#endif /* __NR_mpx */
+
+#define __PNR_newfstatat -10031
+#ifndef __NR_newfstatat
+#define __NR_newfstatat __PNR_newfstatat
+#endif /* __NR_newfstatat */
+
+#define __PNR__newselect -10032
+#ifndef __NR__newselect
+#define __NR__newselect __PNR__newselect
+#endif /* __NR__newselect */
+
+#define __PNR_nice -10033
+#ifndef __NR_nice
+#define __NR_nice __PNR_nice
+#endif /* __NR_nice */
+
+#define __PNR_oldfstat -10034
+#ifndef __NR_oldfstat
+#define __NR_oldfstat __PNR_oldfstat
+#endif /* __NR_oldfstat */
+
+#define __PNR_oldlstat -10035
+#ifndef __NR_oldlstat
+#define __NR_oldlstat __PNR_oldlstat
+#endif /* __NR_oldlstat */
+
+#define __PNR_oldolduname -10036
+#ifndef __NR_oldolduname
+#define __NR_oldolduname __PNR_oldolduname
+#endif /* __NR_oldolduname */
+
+#define __PNR_oldstat -10037
+#ifndef __NR_oldstat
+#define __NR_oldstat __PNR_oldstat
+#endif /* __NR_oldstat */
+
+#define __PNR_olduname -10038
+#ifndef __NR_olduname
+#define __NR_olduname __PNR_olduname
+#endif /* __NR_olduname */
+
+#define __PNR_prof -10039
+#ifndef __NR_prof
+#define __NR_prof __PNR_prof
+#endif /* __NR_prof */
+
+#define __PNR_profil -10040
+#ifndef __NR_profil
+#define __NR_profil __PNR_profil
+#endif /* __NR_profil */
+
+#define __PNR_readdir -10041
+#ifndef __NR_readdir
+#define __NR_readdir __PNR_readdir
+#endif /* __NR_readdir */
+
+#define __PNR_security -10042
+#ifndef __NR_security
+#define __NR_security __PNR_security
+#endif /* __NR_security */
+
+#define __PNR_sendfile64 -10043
+#ifndef __NR_sendfile64
+#define __NR_sendfile64 __PNR_sendfile64
+#endif /* __NR_sendfile64 */
+
+#define __PNR_setfsgid32 -10044
+#ifndef __NR_setfsgid32
+#define __NR_setfsgid32 __PNR_setfsgid32
+#endif /* __NR_setfsgid32 */
+
+#define __PNR_setfsuid32 -10045
+#ifndef __NR_setfsuid32
+#define __NR_setfsuid32 __PNR_setfsuid32
+#endif /* __NR_setfsuid32 */
+
+#define __PNR_setgid32 -10046
+#ifndef __NR_setgid32
+#define __NR_setgid32 __PNR_setgid32
+#endif /* __NR_setgid32 */
+
+#define __PNR_setgroups32 -10047
+#ifndef __NR_setgroups32
+#define __NR_setgroups32 __PNR_setgroups32
+#endif /* __NR_setgroups32 */
+
+#define __PNR_setregid32 -10048
+#ifndef __NR_setregid32
+#define __NR_setregid32 __PNR_setregid32
+#endif /* __NR_setregid32 */
+
+#define __PNR_setresgid32 -10049
+#ifndef __NR_setresgid32
+#define __NR_setresgid32 __PNR_setresgid32
+#endif /* __NR_setresgid32 */
+
+#define __PNR_setresuid32 -10050
+#ifndef __NR_setresuid32
+#define __NR_setresuid32 __PNR_setresuid32
+#endif /* __NR_setresuid32 */
+
+#define __PNR_setreuid32 -10051
+#ifndef __NR_setreuid32
+#define __NR_setreuid32 __PNR_setreuid32
+#endif /* __NR_setreuid32 */
+
+#define __PNR_setuid32 -10052
+#ifndef __NR_setuid32
+#define __NR_setuid32 __PNR_setuid32
+#endif /* __NR_setuid32 */
+
+#define __PNR_sgetmask -10053
+#ifndef __NR_sgetmask
+#define __NR_sgetmask __PNR_sgetmask
+#endif /* __NR_sgetmask */
+
+#define __PNR_sigaction -10054
+#ifndef __NR_sigaction
+#define __NR_sigaction __PNR_sigaction
+#endif /* __NR_sigaction */
+
+#define __PNR_signal -10055
+#ifndef __NR_signal
+#define __NR_signal __PNR_signal
+#endif /* __NR_signal */
+
+#define __PNR_sigpending -10056
+#ifndef __NR_sigpending
+#define __NR_sigpending __PNR_sigpending
+#endif /* __NR_sigpending */
+
+#define __PNR_sigprocmask -10057
+#ifndef __NR_sigprocmask
+#define __NR_sigprocmask __PNR_sigprocmask
+#endif /* __NR_sigprocmask */
+
+#define __PNR_sigreturn -10058
+#ifndef __NR_sigreturn
+#define __NR_sigreturn __PNR_sigreturn
+#endif /* __NR_sigreturn */
+
+#define __PNR_sigsuspend -10059
+#ifndef __NR_sigsuspend
+#define __NR_sigsuspend __PNR_sigsuspend
+#endif /* __NR_sigsuspend */
+
+#define __PNR_socketcall -10060
+#ifndef __NR_socketcall
+#define __NR_socketcall __PNR_socketcall
+#endif /* __NR_socketcall */
+
+#define __PNR_ssetmask -10061
+#ifndef __NR_ssetmask
+#define __NR_ssetmask __PNR_ssetmask
+#endif /* __NR_ssetmask */
+
+#define __PNR_stat64 -10062
+#ifndef __NR_stat64
+#define __NR_stat64 __PNR_stat64
+#endif /* __NR_stat64 */
+
+#define __PNR_statfs64 -10063
+#ifndef __NR_statfs64
+#define __NR_statfs64 __PNR_statfs64
+#endif /* __NR_statfs64 */
+
+#define __PNR_stime -10064
+#ifndef __NR_stime
+#define __NR_stime __PNR_stime
+#endif /* __NR_stime */
+
+#define __PNR_stty -10065
+#ifndef __NR_stty
+#define __NR_stty __PNR_stty
+#endif /* __NR_stty */
+
+#define __PNR_truncate64 -10066
+#ifndef __NR_truncate64
+#define __NR_truncate64 __PNR_truncate64
+#endif /* __NR_truncate64 */
+
+#define __PNR_tuxcall -10067
+#ifndef __NR_tuxcall
+#define __NR_tuxcall __PNR_tuxcall
+#endif /* __NR_tuxcall */
+
+#define __PNR_ugetrlimit -10068
+#ifndef __NR_ugetrlimit
+#define __NR_ugetrlimit __PNR_ugetrlimit
+#endif /* __NR_ugetrlimit */
+
+#define __PNR_ulimit -10069
+#ifndef __NR_ulimit
+#define __NR_ulimit __PNR_ulimit
+#endif /* __NR_ulimit */
+
+#define __PNR_umount -10070
+#ifndef __NR_umount
+#define __NR_umount __PNR_umount
+#endif /* __NR_umount */
+
+#define __PNR_vm86 -10071
+#ifndef __NR_vm86
+#define __NR_vm86 __PNR_vm86
+#endif /* __NR_vm86 */
+
+#define __PNR_vm86old -10072
+#ifndef __NR_vm86old
+#define __NR_vm86old __PNR_vm86old
+#endif /* __NR_vm86old */
+
+#define __PNR_waitpid -10073
+#ifndef __NR_waitpid
+#define __NR_waitpid __PNR_waitpid
+#endif /* __NR_waitpid */
+
+#define __PNR_create_module -10074
+#ifndef __NR_create_module
+#define __NR_create_module __PNR_create_module
+#endif /* __NR_create_module */
+
+#define __PNR_get_kernel_syms -10075
+#ifndef __NR_get_kernel_syms
+#define __NR_get_kernel_syms __PNR_get_kernel_syms
+#endif /* __NR_get_kernel_syms */
+
+#define __PNR_get_thread_area -10076
+#ifndef __NR_get_thread_area
+#define __NR_get_thread_area __PNR_get_thread_area
+#endif /* __NR_get_thread_area */
+
+#define __PNR_nfsservctl -10077
+#ifndef __NR_nfsservctl
+#define __NR_nfsservctl __PNR_nfsservctl
+#endif /* __NR_nfsservctl */
+
+#define __PNR_query_module -10078
+#ifndef __NR_query_module
+#define __NR_query_module __PNR_query_module
+#endif /* __NR_query_module */
+
+#define __PNR_set_thread_area -10079
+#ifndef __NR_set_thread_area
+#define __NR_set_thread_area __PNR_set_thread_area
+#endif /* __NR_set_thread_area */
+
+#define __PNR__sysctl -10080
+#ifndef __NR__sysctl
+#define __NR__sysctl __PNR__sysctl
+#endif /* __NR__sysctl */
+
+#define __PNR_uselib -10081
+#ifndef __NR_uselib
+#define __NR_uselib __PNR_uselib
+#endif /* __NR_uselib */
+
+#define __PNR_vserver -10082
+#ifndef __NR_vserver
+#define __NR_vserver __PNR_vserver
+#endif /* __NR_vserver */
+
+#define __PNR_arm_fadvise64_64 -10083
+#ifndef __NR_arm_fadvise64_64
+#define __NR_arm_fadvise64_64 __PNR_arm_fadvise64_64
+#endif /* __NR_arm_fadvise64_64 */
+
+#define __PNR_arm_sync_file_range -10084
+#ifndef __NR_arm_sync_file_range
+#define __NR_arm_sync_file_range __PNR_arm_sync_file_range
+#endif /* __NR_arm_sync_file_range */
+
+#define __PNR_finit_module -10085
+#ifndef __NR_finit_module
+#define __NR_finit_module __PNR_finit_module
+#endif /* __NR_finit_module */
+
+#define __PNR_pciconfig_iobase -10086
+#ifndef __NR_pciconfig_iobase
+#define __NR_pciconfig_iobase __PNR_pciconfig_iobase
+#endif /* __NR_pciconfig_iobase */
+
+#define __PNR_pciconfig_read -10087
+#ifndef __NR_pciconfig_read
+#define __NR_pciconfig_read __PNR_pciconfig_read
+#endif /* __NR_pciconfig_read */
+
+#define __PNR_pciconfig_write -10088
+#ifndef __NR_pciconfig_write
+#define __NR_pciconfig_write __PNR_pciconfig_write
+#endif /* __NR_pciconfig_write */
+
+#define __PNR_sync_file_range2 -10089
+#ifndef __NR_sync_file_range2
+#define __NR_sync_file_range2 __PNR_sync_file_range2
+#endif /* __NR_sync_file_range2 */
+
+#define __PNR_syscall -10090
+#ifndef __NR_syscall
+#define __NR_syscall __PNR_syscall
+#endif /* __NR_syscall */
+
+#define __PNR_afs_syscall -10091
+#ifndef __NR_afs_syscall
+#define __NR_afs_syscall __PNR_afs_syscall
+#endif /* __NR_afs_syscall */
+
+#define __PNR_fadvise64 -10092
+#ifndef __NR_fadvise64
+#define __NR_fadvise64 __PNR_fadvise64
+#endif /* __NR_fadvise64 */
+
+#define __PNR_getpmsg -10093
+#ifndef __NR_getpmsg
+#define __NR_getpmsg __PNR_getpmsg
+#endif /* __NR_getpmsg */
+
+#define __PNR_ioperm -10094
+#ifndef __NR_ioperm
+#define __NR_ioperm __PNR_ioperm
+#endif /* __NR_ioperm */
+
+#define __PNR_iopl -10095
+#ifndef __NR_iopl
+#define __NR_iopl __PNR_iopl
+#endif /* __NR_iopl */
+
+#define __PNR_kcmp -10096
+#ifndef __NR_kcmp
+#define __NR_kcmp __PNR_kcmp
+#endif /* __NR_kcmp */
+
+#define __PNR_migrate_pages -10097
+#ifndef __NR_migrate_pages
+#define __NR_migrate_pages __PNR_migrate_pages
+#endif /* __NR_migrate_pages */
+
+#define __PNR_modify_ldt -10098
+#ifndef __NR_modify_ldt
+#define __NR_modify_ldt __PNR_modify_ldt
+#endif /* __NR_modify_ldt */
+
+#define __PNR_putpmsg -10099
+#ifndef __NR_putpmsg
+#define __NR_putpmsg __PNR_putpmsg
+#endif /* __NR_putpmsg */
+
+#define __PNR_sync_file_range -10100
+#ifndef __NR_sync_file_range
+#define __NR_sync_file_range __PNR_sync_file_range
+#endif /* __NR_sync_file_range */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+#
+# Enhanced Seccomp Library Installation Defaults
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+INSTALL_PREFIX ?= $(CONF_INSTALL_PREFIX)
+
+INSTALL_SBIN_DIR ?= $(DESTDIR)/$(INSTALL_PREFIX)/sbin
+INSTALL_BIN_DIR ?= $(DESTDIR)/$(INSTALL_PREFIX)/bin
+INSTALL_LIB_DIR ?= $(DESTDIR)/$(CONF_INSTALL_LIBDIR)
+INSTALL_INC_DIR ?= $(DESTDIR)/$(INSTALL_PREFIX)/include
+INSTALL_MAN_DIR ?= $(DESTDIR)/$(INSTALL_PREFIX)/share/man
+
+INSTALL_OWNER ?= $$(id -u)
+INSTALL_GROUP ?= $$(id -g)
--- /dev/null
+#
+# Enhanced Seccomp Library pkg-config Configuration
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+prefix=%%INSTALL_PREFIX%%
+libdir=%%INSTALL_LIBDIR%%
+includedir=${prefix}/include
+
+Name: libseccomp
+Description: The enhanced seccomp library
+URL: http://libseccomp.sf.net
+Version: %%VERSION_RELEASE%%
+Cflags: -I${includedir}
+Libs: -L${libdir} -lseccomp
--- /dev/null
+#
+# Enhanced Seccomp Library Build Macros
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+SHELL = /bin/bash
+
+#
+# simple /bin/bash script to find the top of the tree
+#
+
+TOPDIR := $(shell \
+ ftd() { \
+ cd $$1; \
+ if [[ -r "macros.mk" ]]; then \
+ pwd; \
+ else \
+ ftd "../"; \
+ fi \
+ }; \
+ ftd .)
+
+#
+# build configuration
+#
+
+V ?= 0
+
+CPPFLAGS += -I$(TOPDIR) -I$(TOPDIR)/include
+LIBFLAGS =
+
+CFLAGS ?= -Wl,-z,relro -Wall -O0 -g -fvisibility=hidden
+CFLAGS += -fPIC
+PYCFLAGS ?= -fvisibility=default
+LDFLAGS ?= -z relro -g
+
+#
+# build tools
+#
+
+LN ?= ln
+MV ?= mv
+CAT ?= cat
+ECHO ?= echo
+TAR ?= tar
+MKDIR ?= mkdir
+
+SED ?= sed
+AWK ?= awk
+
+PYTHON ?= /usr/bin/env python
+
+# we require gcc specific functionality
+GCC ?= gcc
+
+INSTALL ?= install
+
+ifeq ($(V),0)
+ MAKE += --quiet --no-print-directory
+ ECHO_INFO ?= $(ECHO) ">> INFO:"
+else
+ ECHO_INFO ?= /bin/true || $(ECHO) ">> INFO:"
+endif
+
+#
+# auto dependencies
+#
+
+MAKEDEP = @$(GCC) $(CPPFLAGS) -MM -MF $(patsubst %.o,%.d,$@) $<;
+MAKEDEP_EXEC = \
+ @$(GCC) $(CPPFLAGS) -MM -MT $(patsubst %.d,%,$@) \
+ -MF $@ $(patsubst %.d,%.c,$@);
+
+ADDDEP = \
+ @adddep_func() { \
+ $(MV) $$1 $$1.dtmp; \
+ $(CAT) $$1.dtmp | $(SED) -e 's/\([^\]\)$$/\1 \\/' | \
+ ( $(CAT) - && $(ECHO) " $$2" ) > $$1; \
+ $(RM) -f $@.dtmp; \
+ }; \
+ adddep_func
+
+#
+# build constants
+#
+
+VERSION_HDR = version.h
+
+#
+# build macros
+#
+
+PY_DISTUTILS = \
+ VERSION_RELEASE="$(VERSION_RELEASE)" \
+ CFLAGS="$(CFLAGS) $(CPPFLAGS) $(PYCFLAGS)" LDFLAGS="$(LDFLAGS)" \
+ $(PYTHON) ./setup.py
+
+ifeq ($(V),0)
+ PY_BUILD = @echo " PYTHON build";
+endif
+PY_BUILD += $(PY_DISTUTILS)
+ifeq ($(V),0)
+ PY_BUILD += -q
+endif
+PY_BUILD += build
+
+ifeq ($(V),0)
+ PY_INSTALL = @echo " PYTHON install";
+endif
+PY_INSTALL += $(PY_DISTUTILS)
+ifeq ($(V),0)
+ PY_INSTALL += -q
+endif
+PY_INSTALL += install
+
+ifeq ($(V),0)
+ COMPILE = @echo " CC $@";
+endif
+COMPILE += $(GCC) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<;
+
+ifeq ($(V),0)
+ COMPILE_EXEC = @echo " CC $@";
+endif
+COMPILE_EXEC += $(GCC) $(CFLAGS) $(CPPFLAGS) -o $@ $< $(LDFLAGS);
+
+ifeq ($(V),0)
+ ARCHIVE = @echo " AR $@";
+endif
+ARCHIVE += $(AR) -cru $@ $?;
+
+ifeq ($(V),0)
+ LINK_EXEC = @echo " LD $@";
+endif
+LINK_EXEC += $(GCC) $(LDFLAGS) -o $@ $^ $(LIBFLAGS);
+
+ifeq ($(V),0)
+ LINK_LIB = @echo " LD $@" \
+ "($(patsubst %.so.$(VERSION_RELEASE),%.so.$(VERSION_MAJOR),$@))";
+endif
+LINK_LIB += $(GCC) $(LDFLAGS) -o $@ $^ -shared \
+ -Wl,-soname=$(patsubst %.so.$(VERSION_RELEASE),%.so.$(VERSION_MAJOR),$@)
+
+#
+# install macros
+#
+
+ifeq ($(V),0)
+ INSTALL_LIB_MACRO = @echo " INSTALL $^ ($(INSTALL_LIB_DIR)/$^)";
+endif
+INSTALL_LIB_MACRO += \
+ basename=$$(echo $^ | sed -e 's/.so.*$$/.so/'); \
+ soname=$$(objdump -p $^ | grep "SONAME" | awk '{print $$2}'); \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) \
+ -d "$(INSTALL_LIB_DIR)"; \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) -m 0755 \
+ $^ "$(INSTALL_LIB_DIR)"; \
+ (cd "$(INSTALL_LIB_DIR)"; $(RM) $$soname); \
+ (cd "$(INSTALL_LIB_DIR)"; $(LN) -s $^ $$soname); \
+ (cd "$(INSTALL_LIB_DIR)"; $(RM) $$basname); \
+ (cd "$(INSTALL_LIB_DIR)"; $(LN) -s $^ $$basename);
+
+ifeq ($(V),0)
+ INSTALL_BIN_MACRO = @echo " INSTALL $^ ($(INSTALL_BIN_DIR)/$^)";
+endif
+INSTALL_BIN_MACRO += \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) \
+ -d "$(INSTALL_BIN_DIR)"; \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) -m 0755 \
+ $^ "$(INSTALL_BIN_DIR)";
+
+ifeq ($(V),0)
+ INSTALL_PC_MACRO = \
+ @echo " INSTALL $$(cat /proc/$$$$/cmdline | awk '{print $$(NF)}')" \
+ " ($(INSTALL_LIB_DIR)/pkgconfig)";
+endif
+INSTALL_PC_MACRO += \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) \
+ -d "$(INSTALL_LIB_DIR)/pkgconfig"; \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) -m 0644 \
+ "$$(cat /proc/$$$$/cmdline | awk '{print $$(NF)}')" \
+ "$(INSTALL_LIB_DIR)/pkgconfig"; \#
+
+ifeq ($(V),0)
+ INSTALL_INC_MACRO = @echo " INSTALL $^ ($(INSTALL_INC_DIR))";
+endif
+INSTALL_INC_MACRO += \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) \
+ -d "$(INSTALL_INC_DIR)"; \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) -m 0644 \
+ $^ "$(INSTALL_INC_DIR)";
+
+ifeq ($(V),0)
+ INSTALL_MAN1_MACRO = \
+ @echo " INSTALL manpages ($(INSTALL_MAN_DIR)/man1)";
+endif
+INSTALL_MAN1_MACRO += \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) \
+ -d "$(INSTALL_MAN_DIR)/man1"; \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) -m 0644 \
+ $^ "$(INSTALL_MAN_DIR)/man1";
+
+ifeq ($(V),0)
+ INSTALL_MAN3_MACRO = \
+ @echo " INSTALL manpages ($(INSTALL_MAN_DIR)/man3)";
+endif
+INSTALL_MAN3_MACRO += \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) \
+ -d "$(INSTALL_MAN_DIR)/man3"; \
+ $(INSTALL) -o $(INSTALL_OWNER) -g $(INSTALL_GROUP) -m 0644 \
+ $^ "$(INSTALL_MAN_DIR)/man3";
+
+#
+# default build targets
+#
+
+%.o: %.c
+ $(MAKEDEP)
+ $(COMPILE)
--- /dev/null
+#
+# Enhanced Seccomp Library Makefile
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+#
+# macros
+#
+
+include ../macros.mk
+
+#
+# configuration
+#
+
+include $(TOPDIR)/version_info.mk
+include $(TOPDIR)/configure.mk
+include $(TOPDIR)/install.mk
+
+LIB_STATIC = libseccomp.a
+LIB_SHARED = libseccomp.so.$(VERSION_RELEASE)
+
+OBJS = \
+ api.o db.o arch.o \
+ arch-x86.o arch-x86-syscalls.o \
+ arch-x86_64.o arch-x86_64-syscalls.o \
+ arch-x32.o arch-x32-syscalls.o \
+ arch-arm.o arch-arm-syscalls.o \
+ hash.o \
+ gen_pfc.o gen_bpf.o
+
+DEPS = $(OBJS:%.o=%.d)
+
+#
+# bindings configuration
+#
+
+BINDINGS =
+
+ifeq ($(CONF_BINDINGS_PYTHON), 1)
+ BINDINGS += python
+endif
+
+#
+# targets
+#
+
+.PHONY: all install clean python
+
+all: $(LIB_STATIC) $(LIB_SHARED) $(BINDINGS)
+
+-include $(DEPS)
+
+$(LIB_STATIC): $(OBJS)
+ $(ARCHIVE)
+
+$(LIB_SHARED): $(OBJS)
+ $(LINK_LIB)
+
+python: $(LIB_STATIC)
+ @$(ECHO_INFO) "building in directory $@/ ..."
+ @$(MAKE) -C $@
+
+install: $(LIB_SHARED)
+ $(INSTALL_LIB_MACRO)
+ @for dir in $(BINDINGS); do \
+ $(ECHO) ">> INFO: installing from $$dir/"; \
+ $(MAKE) -C $$dir install; \
+ done
+
+clean:
+ $(RM) $(DEPS) $(OBJS) $(LIB_STATIC) libseccomp.so.*
+ @for dir in python; do \
+ $(MAKE) -C $$dir clean; \
+ done
+
--- /dev/null
+/**
+ * Seccomp Library API
+ *
+ * Copyright (c) 2012,2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <endian.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/prctl.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+#include "db.h"
+#include "gen_pfc.h"
+#include "gen_bpf.h"
+#include "system.h"
+
+#define API __attribute__((visibility("default")))
+
+/**
+ * Validate a filter context
+ * @param ctx the filter context
+ *
+ * Attempt to validate the provided filter context. Returns zero if the
+ * context is valid, negative values on failure.
+ *
+ */
+static int _ctx_valid(const scmp_filter_ctx *ctx)
+{
+ return db_col_valid((struct db_filter_col *)ctx);
+}
+
+/**
+ * Validate a syscall number
+ * @param syscall the syscall number
+ *
+ * Attempt to perform basic syscall number validation. Returns zero of the
+ * syscall appears valid, negative values on failure.
+ *
+ */
+static int _syscall_valid(int syscall)
+{
+ if (syscall <= -1 && syscall >= -99)
+ return -EINVAL;
+ return 0;
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API scmp_filter_ctx seccomp_init(uint32_t def_action)
+{
+ struct db_filter_col *col;
+ struct db_filter *db;
+
+ if (db_action_valid(def_action) < 0)
+ return NULL;
+
+ col = db_col_init(def_action);
+ if (col == NULL)
+ return NULL;
+ db = db_init(arch_def_native);
+ if (db == NULL)
+ goto init_failure_col;
+
+ if (db_col_db_add(col, db) < 0)
+ goto init_failure_db;
+
+ return col;
+
+init_failure_db:
+ db_release(db);
+init_failure_col:
+ db_col_release(col);
+ return NULL;
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action)
+{
+ int rc;
+ struct db_filter_col *col = (struct db_filter_col *)ctx;
+ struct db_filter *db;
+
+ if (db_col_valid(col) || db_action_valid(def_action) < 0)
+ return -EINVAL;
+
+ db_col_reset(col, def_action);
+
+ db = db_init(arch_def_native);
+ if (db == NULL)
+ return -ENOMEM;
+ rc = db_col_db_add(col, db);
+ if (rc < 0)
+ db_release(db);
+
+ return rc;
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API void seccomp_release(scmp_filter_ctx ctx)
+{
+ if (_ctx_valid(ctx))
+ return;
+
+ db_col_release((struct db_filter_col *)ctx);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_merge(scmp_filter_ctx ctx_dst,
+ scmp_filter_ctx ctx_src)
+{
+ struct db_filter_col *col_dst = (struct db_filter_col *)ctx_dst;
+ struct db_filter_col *col_src = (struct db_filter_col *)ctx_src;
+
+ if (db_col_valid(col_dst) || db_col_valid(col_src))
+ return -EINVAL;
+
+ /* NOTE: only the default action and NNP settings must match */
+ if ((col_dst->attr.act_default != col_src->attr.act_default) ||
+ (col_dst->attr.nnp_enable != col_src->attr.nnp_enable))
+ return -EINVAL;
+
+ return db_col_merge(col_dst, col_src);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API uint32_t seccomp_arch_native(void)
+{
+ return arch_def_native->token;
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_arch_exist(const scmp_filter_ctx ctx,
+ uint32_t arch_token)
+{
+ struct db_filter_col *col = (struct db_filter_col *)ctx;
+
+ if (arch_token == 0)
+ arch_token = arch_def_native->token;
+
+ if (arch_valid(arch_token))
+ return -EINVAL;
+
+ return (db_col_arch_exist(col, arch_token) ? 0 : -EEXIST);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
+{
+ int rc;
+ const struct arch_def *arch;
+ struct db_filter *db;
+ struct db_filter_col *col = (struct db_filter_col *)ctx;
+
+ if (arch_token == 0)
+ arch_token = arch_def_native->token;
+
+ if (arch_valid(arch_token))
+ return -EINVAL;
+ if (db_col_arch_exist(col, arch_token))
+ return -EEXIST;
+
+ arch = arch_def_lookup(arch_token);
+ if (arch == NULL)
+ return -EFAULT;
+ db = db_init(arch);
+ if (db == NULL)
+ return -ENOMEM;
+ rc = db_col_db_add(col, db);
+ if (rc < 0)
+ db_release(db);
+
+ return rc;
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token)
+{
+ struct db_filter_col *col = (struct db_filter_col *)ctx;
+
+ if (arch_token == 0)
+ arch_token = arch_def_native->token;
+
+ if (arch_valid(arch_token))
+ return -EINVAL;
+ if (db_col_arch_exist(col, arch_token) != -EEXIST)
+ return -EEXIST;
+
+ return db_col_db_remove(col, arch_token);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_load(const scmp_filter_ctx ctx)
+{
+ int rc;
+ struct db_filter_col *col;
+ struct bpf_program *program;
+
+ if (_ctx_valid(ctx))
+ return -EINVAL;
+ col = (struct db_filter_col *)ctx;
+
+ program = gen_bpf_generate((struct db_filter_col *)ctx);
+ if (program == NULL)
+ return -ENOMEM;
+ /* attempt to set NO_NEW_PRIVS */
+ if (col->attr.nnp_enable) {
+ rc = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+ if (rc < 0)
+ return -errno;
+ }
+ /* load the filter into the kernel */
+ rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, program);
+ gen_bpf_release(program);
+ if (rc < 0)
+ return -errno;
+
+ return 0;
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_attr_get(const scmp_filter_ctx ctx,
+ enum scmp_filter_attr attr, uint32_t *value)
+{
+ if (_ctx_valid(ctx))
+ return -EINVAL;
+
+ return db_col_attr_get((const struct db_filter_col *)ctx, attr, value);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_attr_set(scmp_filter_ctx ctx,
+ enum scmp_filter_attr attr, uint32_t value)
+{
+ if (_ctx_valid(ctx))
+ return -EINVAL;
+
+ return db_col_attr_set((struct db_filter_col *)ctx, attr, value);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num)
+{
+ const struct arch_def *arch;
+ const char *name;
+
+ if (arch_token == 0)
+ arch_token = arch_def_native->token;
+ if (arch_valid(arch_token))
+ return NULL;
+ arch = arch_def_lookup(arch_token);
+ if (arch == NULL)
+ return NULL;
+
+ name = arch_syscall_resolve_num(arch, num);
+ if (name == NULL)
+ return NULL;
+
+ return strdup(name);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name)
+{
+ const struct arch_def *arch;
+
+ if (name == NULL)
+ return -EINVAL;
+
+ if (arch_token == 0)
+ arch_token = arch_def_native->token;
+ if (arch_valid(arch_token))
+ return -EINVAL;
+ arch = arch_def_lookup(arch_token);
+ if (arch == NULL)
+ return -EFAULT;
+
+ return arch_syscall_resolve_name(arch, name);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_syscall_resolve_name(const char *name)
+{
+ return seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, name);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_syscall_priority(scmp_filter_ctx ctx,
+ int syscall, uint8_t priority)
+{
+ int rc = 0, rc_tmp;
+ unsigned int iter;
+ int sc_tmp;
+ struct db_filter_col *col;
+ struct db_filter *filter;
+
+ if (_ctx_valid(ctx) || _syscall_valid(syscall))
+ return -EINVAL;
+ col = (struct db_filter_col *)ctx;
+
+ for (iter = 0; iter < col->filter_cnt; iter++) {
+ filter = col->filters[iter];
+ sc_tmp = syscall;
+
+ rc_tmp = arch_syscall_translate(filter->arch, &sc_tmp);
+ if (rc_tmp < 0)
+ goto syscall_priority_failure;
+
+ /* if this is a pseudo syscall (syscall < 0) then we need to
+ * rewrite the syscall for some arch specific reason */
+ if (sc_tmp < 0) {
+ /* we set this as a strict op - we don't really care
+ * since priorities are a "best effort" thing - as we
+ * want to catch the -EDOM error and bail on this
+ * architecture */
+ rc_tmp = arch_syscall_rewrite(filter->arch, 1, &sc_tmp);
+ if (rc_tmp == -EDOM)
+ continue;
+ if (rc_tmp < 0)
+ goto syscall_priority_failure;
+ }
+
+ rc_tmp = db_syscall_priority(filter, sc_tmp, priority);
+
+syscall_priority_failure:
+ if (rc == 0 && rc_tmp < 0)
+ rc = rc_tmp;
+ }
+
+ return rc;
+}
+
+/**
+ * Add a new rule to the current filter
+ * @param col the filter collection
+ * @param strict the strict flag
+ * @param action the filter action
+ * @param syscall the syscall number
+ * @param arg_cnt the number of argument filters in the argument filter chain
+ * @param arg_list the argument filter chain, (uint, enum scmp_compare, ulong)
+ *
+ * This function adds a new argument/comparison/value to the seccomp filter for
+ * a syscall; multiple arguments can be specified and they will be chained
+ * together (essentially AND'd together) in the filter. When the strict flag
+ * is true the function will fail if the exact rule can not be added to the
+ * filter, if the strict flag is false the function will not fail if the
+ * function needs to adjust the rule due to architecture specifics. Returns
+ * zero on success, negative values on failure.
+ *
+ */
+static int _seccomp_rule_add(struct db_filter_col *col,
+ bool strict, uint32_t action, int syscall,
+ unsigned int arg_cnt,
+ const struct scmp_arg_cmp *arg_array)
+{
+ int rc = 0, rc_tmp;
+ int sc_tmp;
+ unsigned int iter;
+ unsigned int chain_len;
+ unsigned int arg_num;
+ size_t chain_size;
+ struct db_filter *filter;
+ struct db_api_arg *chain = NULL, *chain_tmp;
+ struct scmp_arg_cmp arg_data;
+
+ if (arg_cnt > 0 && arg_array == NULL)
+ return -EINVAL;
+
+ if (db_col_valid(col) || _syscall_valid(syscall))
+ return -EINVAL;
+
+ rc = db_action_valid(action);
+ if (rc < 0)
+ return rc;
+ if (action == col->attr.act_default)
+ return -EPERM;
+
+ if (strict && col->filter_cnt > 1)
+ return -EOPNOTSUPP;
+
+ /* collect the arguments for the filter rule */
+ chain_len = ARG_COUNT_MAX;
+ chain_size = sizeof(*chain) * chain_len;
+ chain = malloc(chain_size);
+ if (chain == NULL)
+ return -ENOMEM;
+ memset(chain, 0, chain_size);
+ for (iter = 0; iter < arg_cnt; iter++) {
+ arg_data = arg_array[iter];
+ arg_num = arg_data.arg;
+ if (arg_num < chain_len && chain[arg_num].valid == 0) {
+ chain[arg_num].valid = 1;
+ chain[arg_num].arg = arg_num;
+ chain[arg_num].op = arg_data.op;
+ /* XXX - we should check datum/mask size against the
+ * arch definition, e.g. 64 bit datum on x86 */
+ switch (chain[arg_num].op) {
+ case SCMP_CMP_NE:
+ case SCMP_CMP_LT:
+ case SCMP_CMP_LE:
+ case SCMP_CMP_EQ:
+ case SCMP_CMP_GE:
+ case SCMP_CMP_GT:
+ chain[arg_num].mask = DATUM_MAX;
+ chain[arg_num].datum = arg_data.datum_a;
+ break;
+ case SCMP_CMP_MASKED_EQ:
+ chain[arg_num].mask = arg_data.datum_a;
+ chain[arg_num].datum = arg_data.datum_b;
+ break;
+ default:
+ rc = -EINVAL;
+ goto rule_add_return;
+ }
+ } else {
+ rc = -EINVAL;
+ goto rule_add_return;
+ }
+ }
+
+ for (iter = 0; iter < col->filter_cnt; iter++) {
+ filter = col->filters[iter];
+ sc_tmp = syscall;
+
+ rc_tmp = arch_syscall_translate(filter->arch, &sc_tmp);
+ if (rc_tmp < 0)
+ goto rule_add_failure;
+
+ /* if this is a pseudo syscall (syscall < 0) then we need to
+ * rewrite the rule for some arch specific reason */
+ if (sc_tmp < 0) {
+ /* make a private copy of the chain */
+ chain_tmp = malloc(chain_size);
+ if (chain_tmp == NULL) {
+ rc = -ENOMEM;
+ goto rule_add_failure;
+ }
+ memcpy(chain_tmp, chain, chain_size);
+
+ /* mangle the private chain copy */
+ rc_tmp = arch_filter_rewrite(filter->arch, strict,
+ &sc_tmp, chain_tmp);
+ if ((rc == -EDOM) && (!strict)) {
+ free(chain_tmp);
+ continue;
+ }
+ if (rc_tmp < 0) {
+ free(chain_tmp);
+ goto rule_add_failure;
+ }
+
+ /* add the new rule to the existing filter */
+ rc_tmp = db_rule_add(filter, action, sc_tmp, chain_tmp);
+ free(chain_tmp);
+ } else
+ /* add the new rule to the existing filter */
+ rc_tmp = db_rule_add(filter, action, sc_tmp, chain);
+
+rule_add_failure:
+ if (rc == 0 && rc_tmp < 0)
+ rc = rc_tmp;
+ }
+
+rule_add_return:
+ if (chain != NULL)
+ free(chain);
+ return rc;
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_rule_add_array(scmp_filter_ctx ctx,
+ uint32_t action, int syscall,
+ unsigned int arg_cnt,
+ const struct scmp_arg_cmp *arg_array)
+{
+ if (arg_cnt < 0 || arg_cnt > ARG_COUNT_MAX)
+ return -EINVAL;
+
+ return _seccomp_rule_add((struct db_filter_col *)ctx,
+ 0, action, syscall, arg_cnt, arg_array);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_rule_add(scmp_filter_ctx ctx,
+ uint32_t action, int syscall,
+ unsigned int arg_cnt, ...)
+{
+ int rc;
+ int iter;
+ struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
+ va_list arg_list;
+
+ if (arg_cnt < 0 || arg_cnt > ARG_COUNT_MAX)
+ return -EINVAL;
+
+ va_start(arg_list, arg_cnt);
+ for (iter = 0; iter < arg_cnt; ++iter)
+ arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
+ rc = seccomp_rule_add_array(ctx, action, syscall, arg_cnt, arg_array);
+ va_end(arg_list);
+
+ return rc;
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,
+ uint32_t action, int syscall,
+ unsigned int arg_cnt,
+ const struct scmp_arg_cmp *arg_array)
+{
+ if (arg_cnt < 0 || arg_cnt > ARG_COUNT_MAX)
+ return -EINVAL;
+
+ return _seccomp_rule_add((struct db_filter_col *)ctx,
+ 1, action, syscall, arg_cnt, arg_array);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_rule_add_exact(scmp_filter_ctx ctx,
+ uint32_t action, int syscall,
+ unsigned int arg_cnt, ...)
+{
+ int rc;
+ int iter;
+ struct scmp_arg_cmp arg_array[ARG_COUNT_MAX];
+ va_list arg_list;
+
+ if (arg_cnt < 0 || arg_cnt > ARG_COUNT_MAX)
+ return -EINVAL;
+
+ va_start(arg_list, arg_cnt);
+ for (iter = 0; iter < arg_cnt; ++iter)
+ arg_array[iter] = va_arg(arg_list, struct scmp_arg_cmp);
+ rc = seccomp_rule_add_exact_array(ctx,
+ action, syscall, arg_cnt, arg_array);
+ va_end(arg_list);
+
+ return rc;
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)
+{
+ if (_ctx_valid(ctx))
+ return -EINVAL;
+
+ return gen_pfc_generate((struct db_filter_col *)ctx, fd);
+}
+
+/* NOTE - function header comment in include/seccomp.h */
+API int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)
+{
+ int rc;
+ struct bpf_program *program;
+
+ if (_ctx_valid(ctx))
+ return -EINVAL;
+
+ program = gen_bpf_generate((struct db_filter_col *)ctx);
+ if (program == NULL)
+ return -ENOMEM;
+ rc = write(fd, program->blks, BPF_PGM_SIZE(program));
+ gen_bpf_release(program);
+ if (rc < 0)
+ return -errno;
+
+ return 0;
+}
--- /dev/null
+/**
+ * Enhanced Seccomp ARM Syscall Table
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <string.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+#include "arch-arm.h"
+
+#define __NR_OABI_SYSCALL_BASE 0x900000
+
+/* NOTE: we currently only support the ARM EABI, more info at the URL below:
+ * -> http://wiki.embeddedarm.com/wiki/EABI_vs_OABI */
+#if 1
+#define __NR_SYSCALL_BASE 0
+#else
+#define __NR_SYSCALL_BASE __NR_OABI_SYSCALL_BASE
+#endif
+
+/* NOTE: based on Linux 3.8.0-rc5 */
+const struct arch_syscall_def arm_syscall_table[] = { \
+ /* NOTE: arm_sync_file_range() and sync_file_range2() share values */
+ { "accept", (__NR_SYSCALL_BASE + 285) },
+ { "accept4", (__NR_SYSCALL_BASE + 366) },
+ { "access", (__NR_SYSCALL_BASE + 33) },
+ { "acct", (__NR_SYSCALL_BASE + 51) },
+ { "add_key", (__NR_SYSCALL_BASE + 309) },
+ { "adjtimex", (__NR_SYSCALL_BASE + 124) },
+ { "afs_syscall", __PNR_afs_syscall },
+ { "alarm", (__NR_SYSCALL_BASE + 27) },
+ { "arm_fadvise64_64", (__NR_SYSCALL_BASE + 270) },
+ { "arm_sync_file_range", (__NR_SYSCALL_BASE + 341) },
+ { "arch_prctl", __PNR_arch_prctl },
+ { "bdflush", (__NR_SYSCALL_BASE + 134) },
+ { "bind", (__NR_SYSCALL_BASE + 282) },
+ { "break", __PNR_break },
+ { "brk", (__NR_SYSCALL_BASE + 45) },
+ { "capget", (__NR_SYSCALL_BASE + 184) },
+ { "capset", (__NR_SYSCALL_BASE + 185) },
+ { "chdir", (__NR_SYSCALL_BASE + 12) },
+ { "chmod", (__NR_SYSCALL_BASE + 15) },
+ { "chown", (__NR_SYSCALL_BASE + 182) },
+ { "chown32", (__NR_SYSCALL_BASE + 212) },
+ { "chroot", (__NR_SYSCALL_BASE + 61) },
+ { "clock_adjtime", (__NR_SYSCALL_BASE + 372) },
+ { "clock_getres", (__NR_SYSCALL_BASE + 264) },
+ { "clock_gettime", (__NR_SYSCALL_BASE + 263) },
+ { "clock_nanosleep", (__NR_SYSCALL_BASE + 265) },
+ { "clock_settime", (__NR_SYSCALL_BASE + 262) },
+ { "clone", (__NR_SYSCALL_BASE + 120) },
+ { "close", (__NR_SYSCALL_BASE + 6) },
+ { "connect", (__NR_SYSCALL_BASE + 283) },
+ { "creat", (__NR_SYSCALL_BASE + 8) },
+ { "create_module", __PNR_create_module },
+ { "delete_module", (__NR_SYSCALL_BASE + 129) },
+ { "dup", (__NR_SYSCALL_BASE + 41) },
+ { "dup2", (__NR_SYSCALL_BASE + 63) },
+ { "dup3", (__NR_SYSCALL_BASE + 358) },
+ { "epoll_create", (__NR_SYSCALL_BASE + 250) },
+ { "epoll_create1", (__NR_SYSCALL_BASE + 357) },
+ { "epoll_ctl", (__NR_SYSCALL_BASE + 251) },
+ { "epoll_ctl_old", __PNR_epoll_ctl_old },
+ { "epoll_pwait", (__NR_SYSCALL_BASE + 346) },
+ { "epoll_wait", (__NR_SYSCALL_BASE + 252) },
+ { "epoll_wait_old", __PNR_epoll_wait_old },
+ { "eventfd", (__NR_SYSCALL_BASE + 351) },
+ { "eventfd2", (__NR_SYSCALL_BASE + 356) },
+ { "execve", (__NR_SYSCALL_BASE + 11) },
+ { "exit", (__NR_SYSCALL_BASE + 1) },
+ { "exit_group", (__NR_SYSCALL_BASE + 248) },
+ { "faccessat", (__NR_SYSCALL_BASE + 334) },
+ { "fadvise64", __PNR_fadvise64 },
+ { "fadvise64_64", __PNR_fadvise64_64 },
+ { "fallocate", (__NR_SYSCALL_BASE + 352) },
+ { "fanotify_init", (__NR_SYSCALL_BASE + 367) },
+ { "fanotify_mark", (__NR_SYSCALL_BASE + 368) },
+ { "fchdir", (__NR_SYSCALL_BASE + 133) },
+ { "fchmod", (__NR_SYSCALL_BASE + 94) },
+ { "fchmodat", (__NR_SYSCALL_BASE + 333) },
+ { "fchown", (__NR_SYSCALL_BASE + 95) },
+ { "fchown32", (__NR_SYSCALL_BASE + 207) },
+ { "fchownat", (__NR_SYSCALL_BASE + 325) },
+ { "fcntl", (__NR_SYSCALL_BASE + 55) },
+ { "fcntl64", (__NR_SYSCALL_BASE + 221) },
+ { "fdatasync", (__NR_SYSCALL_BASE + 148) },
+ { "fgetxattr", (__NR_SYSCALL_BASE + 231) },
+ { "finit_module", (__NR_SYSCALL_BASE + 379) },
+ { "flistxattr", (__NR_SYSCALL_BASE + 234) },
+ { "flock", (__NR_SYSCALL_BASE + 143) },
+ { "fork", (__NR_SYSCALL_BASE + 2) },
+ { "fremovexattr", (__NR_SYSCALL_BASE + 237) },
+ { "fsetxattr", (__NR_SYSCALL_BASE + 228) },
+ { "fstat", (__NR_SYSCALL_BASE + 108) },
+ { "fstat64", (__NR_SYSCALL_BASE + 197) },
+ { "fstatat64", (__NR_SYSCALL_BASE + 327) },
+ { "fstatfs", (__NR_SYSCALL_BASE + 100) },
+ { "fstatfs64", (__NR_SYSCALL_BASE + 267) },
+ { "fsync", (__NR_SYSCALL_BASE + 118) },
+ { "ftime", __PNR_ftime },
+ { "ftruncate", (__NR_SYSCALL_BASE + 93) },
+ { "ftruncate64", (__NR_SYSCALL_BASE + 194) },
+ { "futex", (__NR_SYSCALL_BASE + 240) },
+ { "futimesat", (__NR_SYSCALL_BASE + 326) },
+ { "get_kernel_syms", __PNR_get_kernel_syms },
+ { "get_mempolicy", (__NR_SYSCALL_BASE + 320) },
+ { "get_robust_list", (__NR_SYSCALL_BASE + 339) },
+ { "get_thread_area", __PNR_get_thread_area },
+ { "getcpu", (__NR_SYSCALL_BASE + 345) },
+ { "getcwd", (__NR_SYSCALL_BASE + 183) },
+ { "getdents", (__NR_SYSCALL_BASE + 141) },
+ { "getdents64", (__NR_SYSCALL_BASE + 217) },
+ { "getegid", (__NR_SYSCALL_BASE + 50) },
+ { "getegid32", (__NR_SYSCALL_BASE + 202) },
+ { "geteuid", (__NR_SYSCALL_BASE + 49) },
+ { "geteuid32", (__NR_SYSCALL_BASE + 201) },
+ { "getgid", (__NR_SYSCALL_BASE + 47) },
+ { "getgid32", (__NR_SYSCALL_BASE + 200) },
+ { "getgroups", (__NR_SYSCALL_BASE + 80) },
+ { "getgroups32", (__NR_SYSCALL_BASE + 205) },
+ { "getitimer", (__NR_SYSCALL_BASE + 105) },
+ { "getpeername", (__NR_SYSCALL_BASE + 287) },
+ { "getpgid", (__NR_SYSCALL_BASE + 132) },
+ { "getpgrp", (__NR_SYSCALL_BASE + 65) },
+ { "getpid", (__NR_SYSCALL_BASE + 20) },
+ { "getpmsg", __PNR_getpmsg },
+ { "getppid", (__NR_SYSCALL_BASE + 64) },
+ { "getpriority", (__NR_SYSCALL_BASE + 96) },
+ { "getresgid", (__NR_SYSCALL_BASE + 171) },
+ { "getresgid32", (__NR_SYSCALL_BASE + 211) },
+ { "getresuid", (__NR_SYSCALL_BASE + 165) },
+ { "getresuid32", (__NR_SYSCALL_BASE + 209) },
+ { "getrlimit", (__NR_SYSCALL_BASE + 76) },
+ { "getrusage", (__NR_SYSCALL_BASE + 77) },
+ { "getsid", (__NR_SYSCALL_BASE + 147) },
+ { "getsockname", (__NR_SYSCALL_BASE + 286) },
+ { "getsockopt", (__NR_SYSCALL_BASE + 295) },
+ { "gettid", (__NR_SYSCALL_BASE + 224) },
+ { "gettimeofday", (__NR_SYSCALL_BASE + 78) },
+ { "getuid", (__NR_SYSCALL_BASE + 24) },
+ { "getuid32", (__NR_SYSCALL_BASE + 199) },
+ { "getxattr", (__NR_SYSCALL_BASE + 229) },
+ { "gtty", __PNR_gtty },
+ { "idle", __PNR_idle },
+ { "init_module", (__NR_SYSCALL_BASE + 128) },
+ { "inotify_add_watch", (__NR_SYSCALL_BASE + 317) },
+ { "inotify_init", (__NR_SYSCALL_BASE + 316) },
+ { "inotify_init1", (__NR_SYSCALL_BASE + 360) },
+ { "inotify_rm_watch", (__NR_SYSCALL_BASE + 318) },
+ { "io_cancel", (__NR_SYSCALL_BASE + 247) },
+ { "io_destroy", (__NR_SYSCALL_BASE + 244) },
+ { "io_getevents", (__NR_SYSCALL_BASE + 245) },
+ { "io_setup", (__NR_SYSCALL_BASE + 243) },
+ { "io_submit", (__NR_SYSCALL_BASE + 246) },
+ { "ioctl", (__NR_SYSCALL_BASE + 54) },
+ { "ioperm", __PNR_ioperm },
+ { "iopl", __PNR_iopl },
+ { "ioprio_get", (__NR_SYSCALL_BASE + 315) },
+ { "ioprio_set", (__NR_SYSCALL_BASE + 314) },
+ { "ipc", (__NR_SYSCALL_BASE + 117) },
+ { "kcmp", __PNR_kcmp },
+ { "kexec_load", (__NR_SYSCALL_BASE + 347) },
+ { "keyctl", (__NR_SYSCALL_BASE + 311) },
+ { "kill", (__NR_SYSCALL_BASE + 37) },
+ { "lchown", (__NR_SYSCALL_BASE + 16) },
+ { "lchown32", (__NR_SYSCALL_BASE + 198) },
+ { "lgetxattr", (__NR_SYSCALL_BASE + 230) },
+ { "link", (__NR_SYSCALL_BASE + 9) },
+ { "linkat", (__NR_SYSCALL_BASE + 330) },
+ { "listen", (__NR_SYSCALL_BASE + 284) },
+ { "listxattr", (__NR_SYSCALL_BASE + 232) },
+ { "llistxattr", (__NR_SYSCALL_BASE + 233) },
+ { "_llseek", (__NR_SYSCALL_BASE + 140) },
+ { "lock", __PNR_lock },
+ { "lookup_dcookie", (__NR_SYSCALL_BASE + 249) },
+ { "lremovexattr", (__NR_SYSCALL_BASE + 236) },
+ { "lseek", (__NR_SYSCALL_BASE + 19) },
+ { "lsetxattr", (__NR_SYSCALL_BASE + 227) },
+ { "lstat", (__NR_SYSCALL_BASE + 107) },
+ { "lstat64", (__NR_SYSCALL_BASE + 196) },
+ { "madvise", (__NR_SYSCALL_BASE + 220) },
+ { "mbind", (__NR_SYSCALL_BASE + 319) },
+ { "migrate_pages", __PNR_migrate_pages },
+ { "mincore", (__NR_SYSCALL_BASE + 219) },
+ { "mkdir", (__NR_SYSCALL_BASE + 39) },
+ { "mkdirat", (__NR_SYSCALL_BASE + 323) },
+ { "mknod", (__NR_SYSCALL_BASE + 14) },
+ { "mknodat", (__NR_SYSCALL_BASE + 324) },
+ { "mlock", (__NR_SYSCALL_BASE + 150) },
+ { "mlockall", (__NR_SYSCALL_BASE + 152) },
+ { "mmap", (__NR_SYSCALL_BASE + 90) },
+ { "mmap2", (__NR_SYSCALL_BASE + 192) },
+ { "modify_ldt", __PNR_modify_ldt },
+ { "mount", (__NR_SYSCALL_BASE + 21) },
+ { "move_pages", (__NR_SYSCALL_BASE + 344) },
+ { "mprotect", (__NR_SYSCALL_BASE + 125) },
+ { "mpx", __PNR_mpx },
+ { "mq_getsetattr", (__NR_SYSCALL_BASE + 279) },
+ { "mq_notify", (__NR_SYSCALL_BASE + 278) },
+ { "mq_open", (__NR_SYSCALL_BASE + 274) },
+ { "mq_timedreceive", (__NR_SYSCALL_BASE + 277) },
+ { "mq_timedsend", (__NR_SYSCALL_BASE + 276) },
+ { "mq_unlink", (__NR_SYSCALL_BASE + 275) },
+ { "mremap", (__NR_SYSCALL_BASE + 163) },
+ { "msgctl", (__NR_SYSCALL_BASE + 304) },
+ { "msgget", (__NR_SYSCALL_BASE + 303) },
+ { "msgrcv", (__NR_SYSCALL_BASE + 302) },
+ { "msgsnd", (__NR_SYSCALL_BASE + 301) },
+ { "msync", (__NR_SYSCALL_BASE + 144) },
+ { "munlock", (__NR_SYSCALL_BASE + 151) },
+ { "munlockall", (__NR_SYSCALL_BASE + 153) },
+ { "munmap", (__NR_SYSCALL_BASE + 91) },
+ { "name_to_handle_at", (__NR_SYSCALL_BASE + 370) },
+ { "nanosleep", (__NR_SYSCALL_BASE + 162) },
+ { "_newselect", (__NR_SYSCALL_BASE + 142) },
+ { "newfstatat", __PNR_newfstatat },
+ { "nfsservctl", (__NR_SYSCALL_BASE + 169) },
+ { "nice", (__NR_SYSCALL_BASE + 34) },
+ { "oldfstat", __PNR_oldfstat },
+ { "oldlstat", __PNR_oldlstat },
+ { "oldolduname", __PNR_oldolduname },
+ { "oldstat", __PNR_oldstat },
+ { "olduname", __PNR_olduname },
+ { "open", (__NR_SYSCALL_BASE + 5) },
+ { "open_by_handle_at", (__NR_SYSCALL_BASE + 371) },
+ { "openat", (__NR_SYSCALL_BASE + 322) },
+ { "pause", (__NR_SYSCALL_BASE + 29) },
+ { "pciconfig_iobase", (__NR_SYSCALL_BASE + 271) },
+ { "pciconfig_read", (__NR_SYSCALL_BASE + 272) },
+ { "pciconfig_write", (__NR_SYSCALL_BASE + 273) },
+ { "perf_event_open", (__NR_SYSCALL_BASE + 364) },
+ { "personality", (__NR_SYSCALL_BASE + 136) },
+ { "pipe", (__NR_SYSCALL_BASE + 42) },
+ { "pipe2", (__NR_SYSCALL_BASE + 359) },
+ { "pivot_root", (__NR_SYSCALL_BASE + 218) },
+ { "poll", (__NR_SYSCALL_BASE + 168) },
+ { "ppoll", (__NR_SYSCALL_BASE + 336) },
+ { "prctl", (__NR_SYSCALL_BASE + 172) },
+ { "pread64", (__NR_SYSCALL_BASE + 180) },
+ { "preadv", (__NR_SYSCALL_BASE + 361) },
+ { "prlimit64", (__NR_SYSCALL_BASE + 369) },
+ { "process_vm_readv", (__NR_SYSCALL_BASE + 376) },
+ { "process_vm_writev", (__NR_SYSCALL_BASE + 377) },
+ { "prof", __PNR_prof },
+ { "profil", __PNR_profil },
+ { "pselect6", (__NR_SYSCALL_BASE + 335) },
+ { "ptrace", (__NR_SYSCALL_BASE + 26) },
+ { "putpmsg", __PNR_putpmsg },
+ { "pwrite64", (__NR_SYSCALL_BASE + 181) },
+ { "pwritev", (__NR_SYSCALL_BASE + 362) },
+ { "query_module", __PNR_query_module },
+ { "quotactl", (__NR_SYSCALL_BASE + 131) },
+ { "read", (__NR_SYSCALL_BASE + 3) },
+ { "readahead", (__NR_SYSCALL_BASE + 225) },
+ { "readdir", (__NR_SYSCALL_BASE + 89) },
+ { "readlink", (__NR_SYSCALL_BASE + 85) },
+ { "readlinkat", (__NR_SYSCALL_BASE + 332) },
+ { "readv", (__NR_SYSCALL_BASE + 145) },
+ { "reboot", (__NR_SYSCALL_BASE + 88) },
+ { "recv", (__NR_SYSCALL_BASE + 291) },
+ { "recvfrom", (__NR_SYSCALL_BASE + 292) },
+ { "recvmmsg", (__NR_SYSCALL_BASE + 365) },
+ { "recvmsg", (__NR_SYSCALL_BASE + 297) },
+ { "remap_file_pages", (__NR_SYSCALL_BASE + 253) },
+ { "removexattr", (__NR_SYSCALL_BASE + 235) },
+ { "rename", (__NR_SYSCALL_BASE + 38) },
+ { "renameat", (__NR_SYSCALL_BASE + 329) },
+ { "request_key", (__NR_SYSCALL_BASE + 310) },
+ { "restart_syscall", (__NR_SYSCALL_BASE + 0) },
+ { "rmdir", (__NR_SYSCALL_BASE + 40) },
+ { "rt_sigaction", (__NR_SYSCALL_BASE + 174) },
+ { "rt_sigpending", (__NR_SYSCALL_BASE + 176) },
+ { "rt_sigprocmask", (__NR_SYSCALL_BASE + 175) },
+ { "rt_sigqueueinfo", (__NR_SYSCALL_BASE + 178) },
+ { "rt_sigreturn", (__NR_SYSCALL_BASE + 173) },
+ { "rt_sigsuspend", (__NR_SYSCALL_BASE + 179) },
+ { "rt_sigtimedwait", (__NR_SYSCALL_BASE + 177) },
+ { "rt_tgsigqueueinfo", (__NR_SYSCALL_BASE + 363) },
+ { "sched_get_priority_max", (__NR_SYSCALL_BASE + 159) },
+ { "sched_get_priority_min", (__NR_SYSCALL_BASE + 160) },
+ { "sched_getaffinity", (__NR_SYSCALL_BASE + 242) },
+ { "sched_getparam", (__NR_SYSCALL_BASE + 155) },
+ { "sched_getscheduler", (__NR_SYSCALL_BASE + 157) },
+ { "sched_rr_get_interval", (__NR_SYSCALL_BASE + 161) },
+ { "sched_setaffinity", (__NR_SYSCALL_BASE + 241) },
+ { "sched_setparam", (__NR_SYSCALL_BASE + 154) },
+ { "sched_setscheduler", (__NR_SYSCALL_BASE + 156) },
+ { "sched_yield", (__NR_SYSCALL_BASE + 158) },
+ { "security", __PNR_security },
+ { "select", (__NR_SYSCALL_BASE + 82) },
+ { "semctl", (__NR_SYSCALL_BASE + 300) },
+ { "semget", (__NR_SYSCALL_BASE + 299) },
+ { "semop", (__NR_SYSCALL_BASE + 298) },
+ { "semtimedop", (__NR_SYSCALL_BASE + 312) },
+ { "send", (__NR_SYSCALL_BASE + 289) },
+ { "sendfile", (__NR_SYSCALL_BASE + 187) },
+ { "sendfile64", (__NR_SYSCALL_BASE + 239) },
+ { "sendmmsg", (__NR_SYSCALL_BASE + 374) },
+ { "sendmsg", (__NR_SYSCALL_BASE + 296) },
+ { "sendto", (__NR_SYSCALL_BASE + 290) },
+ { "set_mempolicy", (__NR_SYSCALL_BASE + 321) },
+ { "set_robust_list", (__NR_SYSCALL_BASE + 338) },
+ { "set_thread_area", __PNR_set_thread_area },
+ { "set_tid_address", (__NR_SYSCALL_BASE + 256) },
+ { "setdomainname", (__NR_SYSCALL_BASE + 121) },
+ { "setfsgid", (__NR_SYSCALL_BASE + 139) },
+ { "setfsgid32", (__NR_SYSCALL_BASE + 216) },
+ { "setfsuid", (__NR_SYSCALL_BASE + 138) },
+ { "setfsuid32", (__NR_SYSCALL_BASE + 215) },
+ { "setgid", (__NR_SYSCALL_BASE + 46) },
+ { "setgid32", (__NR_SYSCALL_BASE + 214) },
+ { "setgroups", (__NR_SYSCALL_BASE + 81) },
+ { "setgroups32", (__NR_SYSCALL_BASE + 206) },
+ { "sethostname", (__NR_SYSCALL_BASE + 74) },
+ { "setitimer", (__NR_SYSCALL_BASE + 104) },
+ { "setns", (__NR_SYSCALL_BASE + 375) },
+ { "setpgid", (__NR_SYSCALL_BASE + 57) },
+ { "setpriority", (__NR_SYSCALL_BASE + 97) },
+ { "setregid", (__NR_SYSCALL_BASE + 71) },
+ { "setregid32", (__NR_SYSCALL_BASE + 204) },
+ { "setresgid", (__NR_SYSCALL_BASE + 170) },
+ { "setresgid32", (__NR_SYSCALL_BASE + 210) },
+ { "setresuid", (__NR_SYSCALL_BASE + 164) },
+ { "setresuid32", (__NR_SYSCALL_BASE + 208) },
+ { "setreuid", (__NR_SYSCALL_BASE + 70) },
+ { "setreuid32", (__NR_SYSCALL_BASE + 203) },
+ { "setrlimit", (__NR_SYSCALL_BASE + 75) },
+ { "setsid", (__NR_SYSCALL_BASE + 66) },
+ { "setsockopt", (__NR_SYSCALL_BASE + 294) },
+ { "settimeofday", (__NR_SYSCALL_BASE + 79) },
+ { "setuid", (__NR_SYSCALL_BASE + 23) },
+ { "setuid32", (__NR_SYSCALL_BASE + 213) },
+ { "setxattr", (__NR_SYSCALL_BASE + 226) },
+ { "sgetmask", __PNR_sgetmask },
+ { "shmat", (__NR_SYSCALL_BASE + 305) },
+ { "shmctl", (__NR_SYSCALL_BASE + 308) },
+ { "shmdt", (__NR_SYSCALL_BASE + 306) },
+ { "shmget", (__NR_SYSCALL_BASE + 307) },
+ { "shutdown", (__NR_SYSCALL_BASE + 293) },
+ { "sigaction", (__NR_SYSCALL_BASE + 67) },
+ { "sigaltstack", (__NR_SYSCALL_BASE + 186) },
+ { "signal", __PNR_signal },
+ { "signalfd", (__NR_SYSCALL_BASE + 349) },
+ { "signalfd4", (__NR_SYSCALL_BASE + 355) },
+ { "sigpending", (__NR_SYSCALL_BASE + 73) },
+ { "sigprocmask", (__NR_SYSCALL_BASE + 126) },
+ { "sigreturn", (__NR_SYSCALL_BASE + 119) },
+ { "sigsuspend", (__NR_SYSCALL_BASE + 72) },
+ { "socket", (__NR_SYSCALL_BASE + 281) },
+ { "socketcall", (__NR_SYSCALL_BASE + 102) },
+ { "socketpair", (__NR_SYSCALL_BASE + 288) },
+ { "splice", (__NR_SYSCALL_BASE + 340) },
+ { "ssetmask", __PNR_ssetmask },
+ { "stat", (__NR_SYSCALL_BASE + 106) },
+ { "stat64", (__NR_SYSCALL_BASE + 195) },
+ { "statfs", (__NR_SYSCALL_BASE + 99) },
+ { "statfs64", (__NR_SYSCALL_BASE + 266) },
+ { "stime", (__NR_SYSCALL_BASE + 25) },
+ { "stty", __PNR_stty },
+ { "swapoff", (__NR_SYSCALL_BASE + 115) },
+ { "swapon", (__NR_SYSCALL_BASE + 87) },
+ { "symlink", (__NR_SYSCALL_BASE + 83) },
+ { "symlinkat", (__NR_SYSCALL_BASE + 331) },
+ { "sync", (__NR_SYSCALL_BASE + 36) },
+ { "sync_file_range", __PNR_sync_file_range },
+ { "sync_file_range2", (__NR_SYSCALL_BASE + 341) },
+ { "syncfs", (__NR_SYSCALL_BASE + 373) },
+ { "syscall", (__NR_SYSCALL_BASE + 113) },
+ { "_sysctl", (__NR_SYSCALL_BASE + 149) },
+ { "sysfs", (__NR_SYSCALL_BASE + 135) },
+ { "sysinfo", (__NR_SYSCALL_BASE + 116) },
+ { "syslog", (__NR_SYSCALL_BASE + 103) },
+ { "tee", (__NR_SYSCALL_BASE + 342) },
+ { "tgkill", (__NR_SYSCALL_BASE + 268) },
+ { "time", (__NR_SYSCALL_BASE + 13) },
+ { "timer_create", (__NR_SYSCALL_BASE + 257) },
+ { "timer_delete", (__NR_SYSCALL_BASE + 261) },
+ { "timer_getoverrun", (__NR_SYSCALL_BASE + 260) },
+ { "timer_gettime", (__NR_SYSCALL_BASE + 259) },
+ { "timer_settime", (__NR_SYSCALL_BASE + 258) },
+ { "timerfd_create", (__NR_SYSCALL_BASE + 350) },
+ { "timerfd_gettime", (__NR_SYSCALL_BASE + 354) },
+ { "timerfd_settime", (__NR_SYSCALL_BASE + 353) },
+ { "times", (__NR_SYSCALL_BASE + 43) },
+ { "tkill", (__NR_SYSCALL_BASE + 238) },
+ { "truncate", (__NR_SYSCALL_BASE + 92) },
+ { "truncate64", (__NR_SYSCALL_BASE + 193) },
+ { "tuxcall", __PNR_tuxcall },
+ { "ugetrlimit", (__NR_SYSCALL_BASE + 191) },
+ { "ulimit", __PNR_ulimit },
+ { "umask", (__NR_SYSCALL_BASE + 60) },
+ { "umount", (__NR_SYSCALL_BASE + 22) },
+ { "umount2", (__NR_SYSCALL_BASE + 52) },
+ { "uname", (__NR_SYSCALL_BASE + 122) },
+ { "unlink", (__NR_SYSCALL_BASE + 10) },
+ { "unlinkat", (__NR_SYSCALL_BASE + 328) },
+ { "unshare", (__NR_SYSCALL_BASE + 337) },
+ { "uselib", (__NR_SYSCALL_BASE + 86) },
+ { "ustat", (__NR_SYSCALL_BASE + 62) },
+ { "utime", (__NR_SYSCALL_BASE + 30) },
+ { "utimensat", (__NR_SYSCALL_BASE + 348) },
+ { "utimes", (__NR_SYSCALL_BASE + 269) },
+ { "vfork", (__NR_SYSCALL_BASE + 190) },
+ { "vhangup", (__NR_SYSCALL_BASE + 111) },
+ { "vm86", __PNR_vm86 },
+ { "vm86old", __PNR_vm86old },
+ { "vmsplice", (__NR_SYSCALL_BASE + 343) },
+ { "vserver", (__NR_SYSCALL_BASE + 313) },
+ { "wait4", (__NR_SYSCALL_BASE + 114) },
+ { "waitid", (__NR_SYSCALL_BASE + 280) },
+ { "waitpid", __PNR_waitpid },
+ { "write", (__NR_SYSCALL_BASE + 4) },
+ { "writev", (__NR_SYSCALL_BASE + 146) },
+ { NULL, __NR_SCMP_ERROR },
+};
+
+/**
+ * Resolve a syscall name to a number
+ * @param name the syscall name
+ *
+ * Resolve the given syscall name to the syscall number using the syscall table.
+ * Returns the syscall number on success, including negative pseudo syscall
+ * numbers; returns __NR_SCMP_ERROR on failure.
+ *
+ */
+int arm_syscall_resolve_name(const char *name)
+{
+ unsigned int iter;
+ const struct arch_syscall_def *table = arm_syscall_table;
+
+ /* XXX - plenty of room for future improvement here */
+ for (iter = 0; table[iter].name != NULL; iter++) {
+ if (strcmp(name, table[iter].name) == 0)
+ return table[iter].num;
+ }
+
+ return __NR_SCMP_ERROR;
+}
+
+/**
+ * Resolve a syscall number to a name
+ * @param num the syscall number
+ *
+ * Resolve the given syscall number to the syscall name using the syscall table.
+ * Returns a pointer to the syscall name string on success, including pseudo
+ * syscall names; returns NULL on failure.
+ *
+ */
+const char *arm_syscall_resolve_num(int num)
+{
+ unsigned int iter;
+ const struct arch_syscall_def *table = arm_syscall_table;
+
+ /* XXX - plenty of room for future improvement here */
+ for (iter = 0; table[iter].num != __NR_SCMP_ERROR; iter++) {
+ if (num == table[iter].num)
+ return table[iter].name;
+ }
+
+ return NULL;
+}
--- /dev/null
+/**
+ * Enhanced Seccomp ARM Specific Code
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <linux/audit.h>
+
+#include "arch.h"
+#include "arch-arm.h"
+
+const struct arch_def arch_def_arm = {
+ .token = SCMP_ARCH_ARM,
+ .token_bpf = AUDIT_ARCH_ARM,
+ .size = ARCH_SIZE_32,
+ .endian = ARCH_ENDIAN_LITTLE,
+};
--- /dev/null
+/**
+ * Enhanced Seccomp ARM Specific Code
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _ARCH_ARM_H
+#define _ARCH_ARM_H
+
+#include <inttypes.h>
+
+#include "arch.h"
+#include "system.h"
+
+#define arm_arg_count_max 6
+
+extern const struct arch_def arch_def_arm;
+
+int arm_syscall_resolve_name(const char *name);
+const char *arm_syscall_resolve_num(int num);
+
+#endif
--- /dev/null
+/**
+ * Enhanced Seccomp x32 Syscall Table
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <string.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+#include "arch-x86_64.h"
+#include "arch-x32.h"
+
+/**
+ * Resolve a syscall name to a number
+ * @param name the syscall name
+ *
+ * Resolve the given syscall name to the syscall number using the syscall table.
+ * Returns the syscall number on success, including negative pseudo syscall
+ * numbers; returns __NR_SCMP_ERROR on failure.
+ *
+ */
+int x32_syscall_resolve_name(const char *name)
+{
+ int syscall;
+
+ syscall = x86_64_syscall_resolve_name(name);
+ if (syscall >= 0)
+ syscall |= X32_SYSCALL_BIT;
+
+ return syscall;
+}
+
+/**
+ * Resolve a syscall number to a name
+ * @param num the syscall number
+ *
+ * Resolve the given syscall number to the syscall name using the syscall table.
+ * Returns a pointer to the syscall name string on success, including pseudo
+ * syscall names; returns NULL on failure.
+ *
+ */
+const char *x32_syscall_resolve_num(int num)
+{
+ int syscall = num;
+
+ if (syscall >= 0)
+ syscall &= (~X32_SYSCALL_BIT);
+
+ return x86_64_syscall_resolve_num(syscall);
+}
--- /dev/null
+/**
+ * Enhanced Seccomp x32 Specific Code
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <linux/audit.h>
+
+#include "arch.h"
+#include "arch-x32.h"
+
+const struct arch_def arch_def_x32 = {
+ .token = SCMP_ARCH_X32,
+ /* NOTE: this seems odd but the kernel treats x32 like x86_64 here */
+ .token_bpf = AUDIT_ARCH_X86_64,
+ .size = ARCH_SIZE_32,
+ .endian = ARCH_ENDIAN_LITTLE,
+};
--- /dev/null
+/**
+ * Enhanced Seccomp x32 Specific Code
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _ARCH_X32_H
+#define _ARCH_X32_H
+
+#include <inttypes.h>
+
+#include "arch.h"
+#include "system.h"
+
+#define X32_SYSCALL_BIT 0x40000000
+
+#define x32_arg_count_max 6
+
+extern const struct arch_def arch_def_x32;
+
+int x32_syscall_resolve_name(const char *name);
+const char *x32_syscall_resolve_num(int num);
+
+#endif
--- /dev/null
+/**
+ * Enhanced Seccomp x86 Syscall Table
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <string.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+#include "arch-x86.h"
+
+/* NOTE: based on Linux 3.4.7 */
+static const struct arch_syscall_def x86_syscall_table[] = { \
+ { "accept", __PNR_accept },
+ { "accept4", __PNR_accept4 },
+ { "access", 33 },
+ { "acct", 51 },
+ { "add_key", 286 },
+ { "adjtimex", 124 },
+ { "afs_syscall", 137 },
+ { "alarm", 27 },
+ { "arm_fadvise64_64", __PNR_arm_fadvise64_64 },
+ { "arm_sync_file_range", __PNR_arm_sync_file_range },
+ { "arch_prctl", __PNR_arch_prctl },
+ { "bdflush", 134 },
+ { "bind", __PNR_bind },
+ { "break", 17 },
+ { "brk", 45 },
+ { "capget", 184 },
+ { "capset", 185 },
+ { "chdir", 12 },
+ { "chmod", 15 },
+ { "chown", 182 },
+ { "chown32", 212 },
+ { "chroot", 61 },
+ { "clock_adjtime", 343 },
+ { "clock_getres", 266 },
+ { "clock_gettime", 265 },
+ { "clock_nanosleep", 267 },
+ { "clock_settime", 264 },
+ { "clone", 120 },
+ { "close", 6 },
+ { "connect", __PNR_connect },
+ { "creat", 8 },
+ { "create_module", 127 },
+ { "delete_module", 129 },
+ { "dup", 41 },
+ { "dup2", 63 },
+ { "dup3", 330 },
+ { "epoll_create", 254 },
+ { "epoll_create1", 329 },
+ { "epoll_ctl", 255 },
+ { "epoll_ctl_old", __PNR_epoll_ctl_old },
+ { "epoll_pwait", 319 },
+ { "epoll_wait", 256 },
+ { "epoll_wait_old", __PNR_epoll_wait_old },
+ { "eventfd", 323 },
+ { "eventfd2", 328 },
+ { "execve", 11 },
+ { "exit", 1 },
+ { "exit_group", 252 },
+ { "faccessat", 307 },
+ { "fadvise64", 250 },
+ { "fadvise64_64", 272 },
+ { "fallocate", 324 },
+ { "fanotify_init", 338 },
+ { "fanotify_mark", 339 },
+ { "fchdir", 133 },
+ { "fchmod", 94 },
+ { "fchmodat", 306 },
+ { "fchown", 95 },
+ { "fchown32", 207 },
+ { "fchownat", 298 },
+ { "fcntl", 55 },
+ { "fcntl64", 221 },
+ { "fdatasync", 148 },
+ { "fgetxattr", 231 },
+ { "finit_module", __PNR_finit_module },
+ { "flistxattr", 234 },
+ { "flock", 143 },
+ { "fork", 2 },
+ { "fremovexattr", 237 },
+ { "fsetxattr", 228 },
+ { "fstat", 108 },
+ { "fstat64", 197 },
+ { "fstatat64", 300 },
+ { "fstatfs", 100 },
+ { "fstatfs64", 269 },
+ { "fsync", 118 },
+ { "ftime", 35 },
+ { "ftruncate", 93 },
+ { "ftruncate64", 194 },
+ { "futex", 240 },
+ { "futimesat", 299 },
+ { "get_kernel_syms", 130 },
+ { "get_mempolicy", 275 },
+ { "get_robust_list", 312 },
+ { "get_thread_area", 244 },
+ { "getcpu", 318 },
+ { "getcwd", 183 },
+ { "getdents", 141 },
+ { "getdents64", 220 },
+ { "getegid", 50 },
+ { "getegid32", 202 },
+ { "geteuid", 49 },
+ { "geteuid32", 201 },
+ { "getgid", 47 },
+ { "getgid32", 200 },
+ { "getgroups", 80 },
+ { "getgroups32", 205 },
+ { "getitimer", 105 },
+ { "getpeername", __PNR_getpeername },
+ { "getpgid", 132 },
+ { "getpgrp", 65 },
+ { "getpid", 20 },
+ { "getpmsg", 188 },
+ { "getppid", 64 },
+ { "getpriority", 96 },
+ { "getresgid", 171 },
+ { "getresgid32", 211 },
+ { "getresuid", 165 },
+ { "getresuid32", 209 },
+ { "getrlimit", 76 },
+ { "getrusage", 77 },
+ { "getsid", 147 },
+ { "getsockname", __PNR_getsockname },
+ { "getsockopt", __PNR_getsockopt },
+ { "gettid", 224 },
+ { "gettimeofday", 78 },
+ { "getuid", 24 },
+ { "getuid32", 199 },
+ { "getxattr", 229 },
+ { "gtty", 32 },
+ { "idle", 112 },
+ { "init_module", 128 },
+ { "inotify_add_watch", 292 },
+ { "inotify_init", 291 },
+ { "inotify_init1", 332 },
+ { "inotify_rm_watch", 293 },
+ { "io_cancel", 249 },
+ { "io_destroy", 246 },
+ { "io_getevents", 247 },
+ { "io_setup", 245 },
+ { "io_submit", 248 },
+ { "ioctl", 54 },
+ { "ioperm", 101 },
+ { "iopl", 110 },
+ { "ioprio_get", 290 },
+ { "ioprio_set", 289 },
+ { "ipc", 117 },
+ { "kcmp", 349 },
+ { "kexec_load", 283 },
+ { "keyctl", 288 },
+ { "kill", 37 },
+ { "lchown", 16 },
+ { "lchown32", 198 },
+ { "lgetxattr", 230 },
+ { "link", 9 },
+ { "linkat", 303 },
+ { "listen", __PNR_listen },
+ { "listxattr", 232 },
+ { "llistxattr", 233 },
+ { "_llseek", 140 },
+ { "lock", 53 },
+ { "lookup_dcookie", 253 },
+ { "lremovexattr", 236 },
+ { "lseek", 19 },
+ { "lsetxattr", 227 },
+ { "lstat", 107 },
+ { "lstat64", 196 },
+ { "madvise", 219 },
+ { "mbind", 274 },
+ { "migrate_pages", 294 },
+ { "mincore", 218 },
+ { "mkdir", 39 },
+ { "mkdirat", 296 },
+ { "mknod", 14 },
+ { "mknodat", 297 },
+ { "mlock", 150 },
+ { "mlockall", 152 },
+ { "mmap", 90 },
+ { "mmap2", 192 },
+ { "modify_ldt", 123 },
+ { "mount", 21 },
+ { "move_pages", 317 },
+ { "mprotect", 125 },
+ { "mpx", 56 },
+ { "mq_getsetattr", 282 },
+ { "mq_notify", 281 },
+ { "mq_open", 277 },
+ { "mq_timedreceive", 280 },
+ { "mq_timedsend", 279 },
+ { "mq_unlink", 278 },
+ { "mremap", 163 },
+ { "msgctl", __PNR_msgctl },
+ { "msgget", __PNR_msgget },
+ { "msgrcv", __PNR_msgrcv },
+ { "msgsnd", __PNR_msgsnd },
+ { "msync", 144 },
+ { "munlock", 151 },
+ { "munlockall", 153 },
+ { "munmap", 91 },
+ { "name_to_handle_at", 341 },
+ { "nanosleep", 162 },
+ { "_newselect", 142 },
+ { "newfstatat", __PNR_newfstatat },
+ { "nfsservctl", 169 },
+ { "nice", 34 },
+ { "oldfstat", 28 },
+ { "oldlstat", 84 },
+ { "oldolduname", 59 },
+ { "oldstat", 18 },
+ { "olduname", 109 },
+ { "open", 5 },
+ { "open_by_handle_at", 342 },
+ { "openat", 295 },
+ { "pause", 29 },
+ { "pciconfig_iobase", __PNR_pciconfig_iobase },
+ { "pciconfig_read", __PNR_pciconfig_read },
+ { "pciconfig_write", __PNR_pciconfig_write },
+ { "perf_event_open", 336 },
+ { "personality", 136 },
+ { "pipe", 42 },
+ { "pipe2", 331 },
+ { "pivot_root", 217 },
+ { "poll", 168 },
+ { "ppoll", 309 },
+ { "prctl", 172 },
+ { "pread64", 180 },
+ { "preadv", 333 },
+ { "prlimit64", 340 },
+ { "process_vm_readv", 347 },
+ { "process_vm_writev", 348 },
+ { "prof", 44 },
+ { "profil", 98 },
+ { "pselect6", 308 },
+ { "ptrace", 26 },
+ { "putpmsg", 189 },
+ { "pwrite64", 181 },
+ { "pwritev", 334 },
+ { "query_module", 167 },
+ { "quotactl", 131 },
+ { "read", 3 },
+ { "readahead", 225 },
+ { "readdir", 89 },
+ { "readlink", 85 },
+ { "readlinkat", 305 },
+ { "readv", 145 },
+ { "reboot", 88 },
+ { "recv", __PNR_recv },
+ { "recvfrom", __PNR_recvfrom },
+ { "recvmmsg", 337 },
+ { "recvmsg", __PNR_recvmsg },
+ { "remap_file_pages", 257 },
+ { "removexattr", 235 },
+ { "rename", 38 },
+ { "renameat", 302 },
+ { "request_key", 287 },
+ { "restart_syscall", 0 },
+ { "rmdir", 40 },
+ { "rt_sigaction", 174 },
+ { "rt_sigpending", 176 },
+ { "rt_sigprocmask", 175 },
+ { "rt_sigqueueinfo", 178 },
+ { "rt_sigreturn", 173 },
+ { "rt_sigsuspend", 179 },
+ { "rt_sigtimedwait", 177 },
+ { "rt_tgsigqueueinfo", 335 },
+ { "sched_get_priority_max", 159 },
+ { "sched_get_priority_min", 160 },
+ { "sched_getaffinity", 242 },
+ { "sched_getparam", 155 },
+ { "sched_getscheduler", 157 },
+ { "sched_rr_get_interval", 161 },
+ { "sched_setaffinity", 241 },
+ { "sched_setparam", 154 },
+ { "sched_setscheduler", 156 },
+ { "sched_yield", 158 },
+ { "security", __PNR_security },
+ { "select", 82 },
+ { "semctl", __PNR_semctl },
+ { "semget", __PNR_semget },
+ { "semop", __PNR_semop },
+ { "semtimedop", __PNR_semtimedop },
+ { "send", __PNR_send },
+ { "sendfile", 187 },
+ { "sendfile64", 239 },
+ { "sendmmsg", 345 },
+ { "sendmsg", __PNR_sendmsg },
+ { "sendto", __PNR_sendto },
+ { "set_mempolicy", 276 },
+ { "set_robust_list", 311 },
+ { "set_thread_area", 243 },
+ { "set_tid_address", 258 },
+ { "setdomainname", 121 },
+ { "setfsgid", 139 },
+ { "setfsgid32", 216 },
+ { "setfsuid", 138 },
+ { "setfsuid32", 215 },
+ { "setgid", 46 },
+ { "setgid32", 214 },
+ { "setgroups", 81 },
+ { "setgroups32", 206 },
+ { "sethostname", 74 },
+ { "setitimer", 104 },
+ { "setns", 346 },
+ { "setpgid", 57 },
+ { "setpriority", 97 },
+ { "setregid", 71 },
+ { "setregid32", 204 },
+ { "setresgid", 170 },
+ { "setresgid32", 210 },
+ { "setresuid", 164 },
+ { "setresuid32", 208 },
+ { "setreuid", 70 },
+ { "setreuid32", 203 },
+ { "setrlimit", 75 },
+ { "setsid", 66 },
+ { "setsockopt", __PNR_setsockopt },
+ { "settimeofday", 79 },
+ { "setuid", 23 },
+ { "setuid32", 213 },
+ { "setxattr", 226 },
+ { "sgetmask", 68 },
+ { "shmat", __PNR_shmat },
+ { "shmctl", __PNR_shmctl },
+ { "shmdt", __PNR_shmdt },
+ { "shmget", __PNR_shmget },
+ { "shutdown", __PNR_shutdown },
+ { "sigaction", 67 },
+ { "sigaltstack", 186 },
+ { "signal", 48 },
+ { "signalfd", 321 },
+ { "signalfd4", 327 },
+ { "sigpending", 73 },
+ { "sigprocmask", 126 },
+ { "sigreturn", 119 },
+ { "sigsuspend", 72 },
+ { "socket", __PNR_socket },
+ { "socketcall", 102 },
+ { "socketpair", __PNR_socketpair },
+ { "splice", 313 },
+ { "ssetmask", 69 },
+ { "stat", 106 },
+ { "stat64", 195 },
+ { "statfs", 99 },
+ { "statfs64", 268 },
+ { "stime", 25 },
+ { "stty", 31 },
+ { "swapoff", 115 },
+ { "swapon", 87 },
+ { "symlink", 83 },
+ { "symlinkat", 304 },
+ { "sync", 36 },
+ { "sync_file_range", 314 },
+ { "sync_file_range2", __PNR_sync_file_range2 },
+ { "syncfs", 344 },
+ { "syscall", __PNR_syscall },
+ { "_sysctl", 149 },
+ { "sysfs", 135 },
+ { "sysinfo", 116 },
+ { "syslog", 103 },
+ { "tee", 315 },
+ { "tgkill", 270 },
+ { "time", 13 },
+ { "timer_create", 259 },
+ { "timer_delete", 263 },
+ { "timer_getoverrun", 262 },
+ { "timer_gettime", 261 },
+ { "timer_settime", 260 },
+ { "timerfd_create", 322 },
+ { "timerfd_gettime", 326 },
+ { "timerfd_settime", 325 },
+ { "times", 43 },
+ { "tkill", 238 },
+ { "truncate", 92 },
+ { "truncate64", 193 },
+ { "tuxcall", __PNR_tuxcall },
+ { "ugetrlimit", 191 },
+ { "ulimit", 58 },
+ { "umask", 60 },
+ { "umount", 22 },
+ { "umount2", 52 },
+ { "uname", 122 },
+ { "unlink", 10 },
+ { "unlinkat", 301 },
+ { "unshare", 310 },
+ { "uselib", 86 },
+ { "ustat", 62 },
+ { "utime", 30 },
+ { "utimensat", 320 },
+ { "utimes", 271 },
+ { "vfork", 190 },
+ { "vhangup", 111 },
+ { "vm86", 166 },
+ { "vm86old", 113 },
+ { "vmsplice", 316 },
+ { "vserver", 273 },
+ { "wait4", 114 },
+ { "waitid", 284 },
+ { "waitpid", 7 },
+ { "write", 4 },
+ { "writev", 146 },
+ { NULL, __NR_SCMP_ERROR },
+};
+
+/**
+ * Resolve a syscall name to a number
+ * @param name the syscall name
+ *
+ * Resolve the given syscall name to the syscall number using the syscall table.
+ * Returns the syscall number on success, including negative pseudo syscall
+ * numbers; returns __NR_SCMP_ERROR on failure.
+ *
+ */
+int x86_syscall_resolve_name(const char *name)
+{
+ unsigned int iter;
+ const struct arch_syscall_def *table = x86_syscall_table;
+
+ /* XXX - plenty of room for future improvement here */
+ for (iter = 0; table[iter].name != NULL; iter++) {
+ if (strcmp(name, table[iter].name) == 0)
+ return table[iter].num;
+ }
+
+ return __NR_SCMP_ERROR;
+}
+
+/**
+ * Resolve a syscall number to a name
+ * @param num the syscall number
+ *
+ * Resolve the given syscall number to the syscall name using the syscall table.
+ * Returns a pointer to the syscall name string on success, including pseudo
+ * syscall names; returns NULL on failure.
+ *
+ */
+const char *x86_syscall_resolve_num(int num)
+{
+ unsigned int iter;
+ const struct arch_syscall_def *table = x86_syscall_table;
+
+ /* XXX - plenty of room for future improvement here */
+ for (iter = 0; table[iter].num != __NR_SCMP_ERROR; iter++) {
+ if (num == table[iter].num)
+ return table[iter].name;
+ }
+
+ return NULL;
+}
--- /dev/null
+/**
+ * Enhanced Seccomp x86 Specific Code
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <linux/audit.h>
+
+#include "arch.h"
+#include "arch-x86.h"
+
+/* x86 syscall numbers */
+#define __x86_NR_socketcall 102
+#define __x86_NR_ipc 117
+
+const struct arch_def arch_def_x86 = {
+ .token = SCMP_ARCH_X86,
+ .token_bpf = AUDIT_ARCH_I386,
+ .size = ARCH_SIZE_32,
+ .endian = ARCH_ENDIAN_LITTLE,
+};
+
+/**
+ * Rewrite a syscall value to match the architecture
+ * @param arch the architecture definition
+ * @param strict strict flag
+ * @param syscall the syscall number
+ *
+ * Syscalls can vary across different architectures so this function rewrites
+ * the syscall into the correct value for the specified architecture. If
+ * @strict is true then the function will fail if the syscall can not be
+ * preservered, however, if @strict is false the function will do a "best
+ * effort" rewrite and not fail. Returns zero on success, negative values on
+ * failure.
+ *
+ */
+int x86_syscall_rewrite(const struct arch_def *arch, bool strict, int *syscall)
+{
+ if ((*syscall) <= -100 && (*syscall) >= -117)
+ *syscall = __x86_NR_socketcall;
+ else if ((*syscall) <= -200 && (*syscall) >= -211)
+ *syscall = __x86_NR_ipc;
+ else if (((*syscall) < 0) && (strict))
+ return -EDOM;
+
+ return 0;
+}
+
+/**
+ * Rewrite a filter rule to match the architecture specifics
+ * @param arch the architecture definition
+ * @param strict strict flag
+ * @param syscall the syscall number
+ * @param chain the argument filter chain
+ *
+ * Syscalls can vary across different architectures so this function handles
+ * the necessary seccomp rule rewrites to ensure the right thing is done
+ * regardless of the rule or architecture. If @strict is true then the
+ * function will fail if the entire filter can not be preservered, however,
+ * if @strict is false the function will do a "best effort" rewrite and not
+ * fail. Returns zero on success, negative values on failure.
+ *
+ */
+int x86_filter_rewrite(const struct arch_def *arch, bool strict,
+ int *syscall, struct db_api_arg *chain)
+{
+ unsigned int iter;
+
+ if ((*syscall) <= -100 && (*syscall) >= -117) {
+ for (iter = 0; iter < x86_arg_count_max; iter++) {
+ if ((chain[iter].valid != 0) && (strict))
+ return -EINVAL;
+ }
+ chain[0].arg = 0;
+ chain[0].op = SCMP_CMP_EQ;
+ chain[0].mask = DATUM_MAX;
+ chain[0].datum = abs(*syscall) % 100;
+ chain[0].valid = 1;
+ *syscall = __x86_NR_socketcall;
+ } else if ((*syscall) <= -200 && (*syscall) >= -211) {
+ for (iter = 0; iter < x86_arg_count_max; iter++) {
+ if ((chain[iter].valid != 0) && (strict))
+ return -EINVAL;
+ }
+ chain[0].arg = 0;
+ chain[0].op = SCMP_CMP_EQ;
+ chain[0].mask = DATUM_MAX;
+ chain[0].datum = abs(*syscall) % 200;
+ chain[0].valid = 1;
+ *syscall = __x86_NR_ipc;
+ } else if (((*syscall) < 0) && (strict))
+ return -EDOM;
+
+ return 0;
+}
--- /dev/null
+/**
+ * Enhanced Seccomp x86 Specific Code
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _ARCH_X86_H
+#define _ARCH_X86_H
+
+#include <stdbool.h>
+
+#include "arch.h"
+#include "db.h"
+#include "system.h"
+
+#define x86_arg_count_max 6
+
+extern const struct arch_def arch_def_x86;
+
+int x86_syscall_resolve_name(const char *name);
+const char *x86_syscall_resolve_num(int num);
+
+int x86_syscall_rewrite(const struct arch_def *arch, bool strict, int *syscall);
+
+int x86_filter_rewrite(const struct arch_def *arch, bool strict,
+ int *syscall, struct db_api_arg *chain);
+
+#endif
--- /dev/null
+/**
+ * Enhanced Seccomp x86_64 Syscall Table
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <string.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+#include "arch-x86_64.h"
+
+/* NOTE: based on Linux 3.4.7 */
+const struct arch_syscall_def x86_64_syscall_table[] = { \
+ { "accept", 43 },
+ { "accept4", 288 },
+ { "access", 21 },
+ { "acct", 163 },
+ { "add_key", 248 },
+ { "adjtimex", 159 },
+ { "afs_syscall", 183 },
+ { "alarm", 37 },
+ { "arm_fadvise64_64", __PNR_arm_fadvise64_64 },
+ { "arm_sync_file_range", __PNR_arm_sync_file_range },
+ { "arch_prctl", 158 },
+ { "bdflush", __PNR_bdflush },
+ { "bind", 49 },
+ { "break", __PNR_break },
+ { "brk", 12 },
+ { "capget", 125 },
+ { "capset", 126 },
+ { "chdir", 80 },
+ { "chmod", 90 },
+ { "chown", 92 },
+ { "chown32", __PNR_chown32 },
+ { "chroot", 161 },
+ { "clock_adjtime", 305 },
+ { "clock_getres", 229 },
+ { "clock_gettime", 228 },
+ { "clock_nanosleep", 230 },
+ { "clock_settime", 227 },
+ { "clone", 56 },
+ { "close", 3 },
+ { "connect", 42 },
+ { "creat", 85 },
+ { "create_module", 174 },
+ { "delete_module", 176 },
+ { "dup", 32 },
+ { "dup2", 33 },
+ { "dup3", 292 },
+ { "epoll_create", 213 },
+ { "epoll_create1", 291 },
+ { "epoll_ctl", 233 },
+ { "epoll_ctl_old", 214 },
+ { "epoll_pwait", 281 },
+ { "epoll_wait", 232 },
+ { "epoll_wait_old", 215 },
+ { "eventfd", 284 },
+ { "eventfd2", 290 },
+ { "execve", 59 },
+ { "exit", 60 },
+ { "exit_group", 231 },
+ { "faccessat", 269 },
+ { "fadvise64", 221 },
+ { "fadvise64_64", __PNR_fadvise64_64 },
+ { "fallocate", 285 },
+ { "fanotify_init", 300 },
+ { "fanotify_mark", 301 },
+ { "fchdir", 81 },
+ { "fchmod", 91 },
+ { "fchmodat", 268 },
+ { "fchown", 93 },
+ { "fchown32", __PNR_fchown32 },
+ { "fchownat", 260 },
+ { "fcntl", 72 },
+ { "fcntl64", __PNR_fcntl64 },
+ { "fdatasync", 75 },
+ { "fgetxattr", 193 },
+ { "finit_module", __PNR_finit_module },
+ { "flistxattr", 196 },
+ { "flock", 73 },
+ { "fork", 57 },
+ { "fremovexattr", 199 },
+ { "fsetxattr", 190 },
+ { "fstat", 5 },
+ { "fstat64", __PNR_fstat64 },
+ { "fstatat64", __PNR_fstatat64 },
+ { "fstatfs", 138 },
+ { "fstatfs64", __PNR_fstatfs64 },
+ { "fsync", 74 },
+ { "ftime", __PNR_ftime },
+ { "ftruncate", 77 },
+ { "ftruncate64", __PNR_ftruncate64 },
+ { "futex", 202 },
+ { "futimesat", 261 },
+ { "get_kernel_syms", 177 },
+ { "get_mempolicy", 239 },
+ { "get_robust_list", 274 },
+ { "get_thread_area", 211 },
+ { "getcpu", 309 },
+ { "getcwd", 79 },
+ { "getdents", 78 },
+ { "getdents64", 217 },
+ { "getegid", 108 },
+ { "getegid32", __PNR_getegid32 },
+ { "geteuid", 107 },
+ { "geteuid32", __PNR_geteuid32 },
+ { "getgid", 104 },
+ { "getgid32", __PNR_getgid32 },
+ { "getgroups", 115 },
+ { "getgroups32", __PNR_getgroups32 },
+ { "getitimer", 36 },
+ { "getpeername", 52 },
+ { "getpgid", 121 },
+ { "getpgrp", 111 },
+ { "getpid", 39 },
+ { "getpmsg", 181 },
+ { "getppid", 110 },
+ { "getpriority", 140 },
+ { "getresgid", 120 },
+ { "getresgid32", __PNR_getresgid32 },
+ { "getresuid", 118 },
+ { "getresuid32", __PNR_getresuid32 },
+ { "getrlimit", 97 },
+ { "getrusage", 98 },
+ { "getsid", 124 },
+ { "getsockname", 51 },
+ { "getsockopt", 55 },
+ { "gettid", 186 },
+ { "gettimeofday", 96 },
+ { "getuid", 102 },
+ { "getuid32", __PNR_getuid32 },
+ { "getxattr", 191 },
+ { "gtty", __PNR_gtty },
+ { "idle", __PNR_idle },
+ { "init_module", 175 },
+ { "inotify_add_watch", 254 },
+ { "inotify_init", 253 },
+ { "inotify_init1", 294 },
+ { "inotify_rm_watch", 255 },
+ { "io_cancel", 210 },
+ { "io_destroy", 207 },
+ { "io_getevents", 208 },
+ { "io_setup", 206 },
+ { "io_submit", 209 },
+ { "ioctl", 16 },
+ { "ioperm", 173 },
+ { "iopl", 172 },
+ { "ioprio_get", 252 },
+ { "ioprio_set", 251 },
+ { "ipc", __PNR_ipc },
+ { "kcmp", 312 },
+ { "kexec_load", 246 },
+ { "keyctl", 250 },
+ { "kill", 62 },
+ { "lchown", 94 },
+ { "lchown32", __PNR_lchown32 },
+ { "lgetxattr", 192 },
+ { "link", 86 },
+ { "linkat", 265 },
+ { "listen", 50 },
+ { "listxattr", 194 },
+ { "llistxattr", 195 },
+ { "_llseek", __PNR__llseek },
+ { "lock", __PNR_lock },
+ { "lookup_dcookie", 212 },
+ { "lremovexattr", 198 },
+ { "lseek", 8 },
+ { "lsetxattr", 189 },
+ { "lstat", 6 },
+ { "lstat64", __PNR_lstat64 },
+ { "madvise", 28 },
+ { "mbind", 237 },
+ { "migrate_pages", 256 },
+ { "mincore", 27 },
+ { "mkdir", 83 },
+ { "mkdirat", 258 },
+ { "mknod", 133 },
+ { "mknodat", 259 },
+ { "mlock", 149 },
+ { "mlockall", 151 },
+ { "mmap", 9 },
+ { "mmap2", __PNR_mmap2 },
+ { "modify_ldt", 154 },
+ { "mount", 165 },
+ { "move_pages", 279 },
+ { "mprotect", 10 },
+ { "mpx", __PNR_mpx },
+ { "mq_getsetattr", 245 },
+ { "mq_notify", 244 },
+ { "mq_open", 240 },
+ { "mq_timedreceive", 243 },
+ { "mq_timedsend", 242 },
+ { "mq_unlink", 241 },
+ { "mremap", 25 },
+ { "msgctl", 71 },
+ { "msgget", 68 },
+ { "msgrcv", 70 },
+ { "msgsnd", 69 },
+ { "msync", 26 },
+ { "munlock", 150 },
+ { "munlockall", 152 },
+ { "munmap", 11 },
+ { "name_to_handle_at", 303 },
+ { "nanosleep", 35 },
+ { "_newselect", __PNR__newselect },
+ { "newfstatat", 262 },
+ { "nfsservctl", 180 },
+ { "nice", __PNR_nice },
+ { "oldfstat", __PNR_oldfstat },
+ { "oldlstat", __PNR_oldlstat },
+ { "oldolduname", __PNR_oldolduname },
+ { "oldstat", __PNR_oldstat },
+ { "olduname", __PNR_olduname },
+ { "open", 2 },
+ { "open_by_handle_at", 304 },
+ { "openat", 257 },
+ { "pause", 34 },
+ { "pciconfig_iobase", __PNR_pciconfig_iobase },
+ { "pciconfig_read", __PNR_pciconfig_read },
+ { "pciconfig_write", __PNR_pciconfig_write },
+ { "perf_event_open", 298 },
+ { "personality", 135 },
+ { "pipe", 22 },
+ { "pipe2", 293 },
+ { "pivot_root", 155 },
+ { "poll", 7 },
+ { "ppoll", 271 },
+ { "prctl", 157 },
+ { "pread64", 17 },
+ { "preadv", 295 },
+ { "prlimit64", 302 },
+ { "process_vm_readv", 310 },
+ { "process_vm_writev", 311 },
+ { "prof", __PNR_prof },
+ { "profil", __PNR_profil },
+ { "pselect6", 270 },
+ { "ptrace", 101 },
+ { "putpmsg", 182 },
+ { "pwrite64", 18 },
+ { "pwritev", 296 },
+ { "query_module", 178 },
+ { "quotactl", 179 },
+ { "read", 0 },
+ { "readahead", 187 },
+ { "readdir", __PNR_readdir },
+ { "readlink", 89 },
+ { "readlinkat", 267 },
+ { "readv", 19 },
+ { "reboot", 169 },
+ { "recv", __PNR_recv },
+ { "recvfrom", 45 },
+ { "recvmmsg", 299 },
+ { "recvmsg", 47 },
+ { "remap_file_pages", 216 },
+ { "removexattr", 197 },
+ { "rename", 82 },
+ { "renameat", 264 },
+ { "request_key", 249 },
+ { "restart_syscall", 219 },
+ { "rmdir", 84 },
+ { "rt_sigaction", 13 },
+ { "rt_sigpending", 127 },
+ { "rt_sigprocmask", 14 },
+ { "rt_sigqueueinfo", 129 },
+ { "rt_sigreturn", 15 },
+ { "rt_sigsuspend", 130 },
+ { "rt_sigtimedwait", 128 },
+ { "rt_tgsigqueueinfo", 297 },
+ { "sched_get_priority_max", 146 },
+ { "sched_get_priority_min", 147 },
+ { "sched_getaffinity", 204 },
+ { "sched_getparam", 143 },
+ { "sched_getscheduler", 145 },
+ { "sched_rr_get_interval", 148 },
+ { "sched_setaffinity", 203 },
+ { "sched_setparam", 142 },
+ { "sched_setscheduler", 144 },
+ { "sched_yield", 24 },
+ { "security", 185 },
+ { "select", 23 },
+ { "semctl", 66 },
+ { "semget", 64 },
+ { "semop", 65 },
+ { "semtimedop", 220 },
+ { "send", __PNR_send },
+ { "sendfile", 40 },
+ { "sendfile64", __PNR_sendfile64 },
+ { "sendmmsg", 307 },
+ { "sendmsg", 46 },
+ { "sendto", 44 },
+ { "set_mempolicy", 238 },
+ { "set_robust_list", 273 },
+ { "set_thread_area", 205 },
+ { "set_tid_address", 218 },
+ { "setdomainname", 171 },
+ { "setfsgid", 123 },
+ { "setfsgid32", __PNR_setfsgid32 },
+ { "setfsuid", 122 },
+ { "setfsuid32", __PNR_setfsuid32 },
+ { "setgid", 106 },
+ { "setgid32", __PNR_setgid32 },
+ { "setgroups", 116 },
+ { "setgroups32", __PNR_setgroups32 },
+ { "sethostname", 170 },
+ { "setitimer", 38 },
+ { "setns", 308 },
+ { "setpgid", 109 },
+ { "setpriority", 141 },
+ { "setregid", 114 },
+ { "setregid32", __PNR_setregid32 },
+ { "setresgid", 119 },
+ { "setresgid32", __PNR_setresgid32 },
+ { "setresuid", 117 },
+ { "setresuid32", __PNR_setresuid32 },
+ { "setreuid", 113 },
+ { "setreuid32", __PNR_setreuid32 },
+ { "setrlimit", 160 },
+ { "setsid", 112 },
+ { "setsockopt", 54 },
+ { "settimeofday", 164 },
+ { "setuid", 105 },
+ { "setuid32", __PNR_setuid32 },
+ { "setxattr", 188 },
+ { "sgetmask", __PNR_sgetmask },
+ { "shmat", 30 },
+ { "shmctl", 31 },
+ { "shmdt", 67 },
+ { "shmget", 29 },
+ { "shutdown", 48 },
+ { "sigaction", __PNR_sigaction },
+ { "sigaltstack", 131 },
+ { "signal", __PNR_signal },
+ { "signalfd", 282 },
+ { "signalfd4", 289 },
+ { "sigpending", __PNR_sigpending },
+ { "sigprocmask", __PNR_sigprocmask },
+ { "sigreturn", __PNR_sigreturn },
+ { "sigsuspend", __PNR_sigsuspend },
+ { "socket", 41 },
+ { "socketcall", __PNR_socketcall },
+ { "socketpair", 53 },
+ { "splice", 275 },
+ { "ssetmask", __PNR_ssetmask },
+ { "stat", 4 },
+ { "stat64", __PNR_stat64 },
+ { "statfs", 137 },
+ { "statfs64", __PNR_statfs64 },
+ { "stime", __PNR_stime },
+ { "stty", __PNR_stty },
+ { "swapoff", 168 },
+ { "swapon", 167 },
+ { "symlink", 88 },
+ { "symlinkat", 266 },
+ { "sync", 162 },
+ { "sync_file_range", 277 },
+ { "sync_file_range2", __PNR_sync_file_range2 },
+ { "syncfs", 306 },
+ { "syscall", __PNR_syscall },
+ { "_sysctl", 156 },
+ { "sysfs", 139 },
+ { "sysinfo", 99 },
+ { "syslog", 103 },
+ { "tee", 276 },
+ { "tgkill", 234 },
+ { "time", 201 },
+ { "timer_create", 222 },
+ { "timer_delete", 226 },
+ { "timer_getoverrun", 225 },
+ { "timer_gettime", 224 },
+ { "timer_settime", 223 },
+ { "timerfd_create", 283 },
+ { "timerfd_gettime", 287 },
+ { "timerfd_settime", 286 },
+ { "times", 100 },
+ { "tkill", 200 },
+ { "truncate", 76 },
+ { "truncate64", __PNR_truncate64 },
+ { "tuxcall", 184 },
+ { "ugetrlimit", __PNR_ugetrlimit },
+ { "ulimit", __PNR_ulimit },
+ { "umask", 95 },
+ { "umount", __PNR_umount },
+ { "umount2", 166 },
+ { "uname", 63 },
+ { "unlink", 87 },
+ { "unlinkat", 263 },
+ { "unshare", 272 },
+ { "uselib", 134 },
+ { "ustat", 136 },
+ { "utime", 132 },
+ { "utimensat", 280 },
+ { "utimes", 235 },
+ { "vfork", 58 },
+ { "vhangup", 153 },
+ { "vm86", __PNR_vm86 },
+ { "vm86old", __PNR_vm86old },
+ { "vmsplice", 278 },
+ { "vserver", 236 },
+ { "wait4", 61 },
+ { "waitid", 247 },
+ { "waitpid", __PNR_waitpid },
+ { "write", 1 },
+ { "writev", 20 },
+ { NULL, __NR_SCMP_ERROR },
+};
+
+/**
+ * Resolve a syscall name to a number
+ * @param name the syscall name
+ *
+ * Resolve the given syscall name to the syscall number using the syscall table.
+ * Returns the syscall number on success, including negative pseudo syscall
+ * numbers; returns __NR_SCMP_ERROR on failure.
+ *
+ */
+int x86_64_syscall_resolve_name(const char *name)
+{
+ unsigned int iter;
+ const struct arch_syscall_def *table = x86_64_syscall_table;
+
+ /* XXX - plenty of room for future improvement here */
+ for (iter = 0; table[iter].name != NULL; iter++) {
+ if (strcmp(name, table[iter].name) == 0)
+ return table[iter].num;
+ }
+
+ return __NR_SCMP_ERROR;
+}
+
+/**
+ * Resolve a syscall number to a name
+ * @param num the syscall number
+ *
+ * Resolve the given syscall number to the syscall name using the syscall table.
+ * Returns a pointer to the syscall name string on success, including pseudo
+ * syscall names; returns NULL on failure.
+ *
+ */
+const char *x86_64_syscall_resolve_num(int num)
+{
+ unsigned int iter;
+ const struct arch_syscall_def *table = x86_64_syscall_table;
+
+ /* XXX - plenty of room for future improvement here */
+ for (iter = 0; table[iter].num != __NR_SCMP_ERROR; iter++) {
+ if (num == table[iter].num)
+ return table[iter].name;
+ }
+
+ return NULL;
+}
--- /dev/null
+/**
+ * Enhanced Seccomp x86_64 Specific Code
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <stdlib.h>
+#include <errno.h>
+#include <linux/audit.h>
+
+#include "arch.h"
+#include "arch-x86_64.h"
+
+const struct arch_def arch_def_x86_64 = {
+ .token = SCMP_ARCH_X86_64,
+ .token_bpf = AUDIT_ARCH_X86_64,
+ .size = ARCH_SIZE_64,
+ .endian = ARCH_ENDIAN_LITTLE,
+};
--- /dev/null
+/**
+ * Enhanced Seccomp x86_64 Specific Code
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _ARCH_x86_64_H
+#define _ARCH_x86_64_H
+
+#include <inttypes.h>
+
+#include "arch.h"
+#include "system.h"
+
+#define x86_64_arg_count_max 6
+
+extern const struct arch_def arch_def_x86_64;
+
+#define x86_64_arg_offset_lo(x) (arch_arg_offset(x))
+#define x86_64_arg_offset_hi(x) (arch_arg_offset(x) + 4)
+
+int x86_64_syscall_resolve_name(const char *name);
+const char *x86_64_syscall_resolve_num(int num);
+
+#endif
--- /dev/null
+/**
+ * Enhanced Seccomp Architecture/Machine Specific Code
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <elf.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <asm/bitsperlong.h>
+#include <linux/audit.h>
+#include <stdbool.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+#include "arch-x86.h"
+#include "arch-x86_64.h"
+#include "arch-x32.h"
+#include "arch-arm.h"
+#include "system.h"
+
+#if __i386__
+const struct arch_def *arch_def_native = &arch_def_x86;
+#elif __x86_64__
+#ifdef __ILP32__
+const struct arch_def *arch_def_native = &arch_def_x32;
+#else
+const struct arch_def *arch_def_native = &arch_def_x86_64;
+#endif /* __ILP32__ */
+#elif __arm__
+const struct arch_def *arch_def_native = &arch_def_arm;
+#else
+#error the arch code needs to know about your machine type
+#endif /* machine type guess */
+
+/**
+ * Validate the architecture token
+ * @param arch the architecture token
+ *
+ * Verify the given architecture token; return zero if valid, -EINVAL if not.
+ *
+ */
+int arch_valid(uint32_t arch)
+{
+ switch (arch) {
+ case SCMP_ARCH_X86:
+ case SCMP_ARCH_X86_64:
+ case SCMP_ARCH_X32:
+ case SCMP_ARCH_ARM:
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+/**
+ * Lookup the architecture definition
+ * @param token the architecure token
+ *
+ * Return the matching architecture definition, returns NULL on failure.
+ *
+ */
+const struct arch_def *arch_def_lookup(uint32_t token)
+{
+ switch (token) {
+ case SCMP_ARCH_X86:
+ return &arch_def_x86;
+ case SCMP_ARCH_X86_64:
+ return &arch_def_x86_64;
+ case SCMP_ARCH_X32:
+ return &arch_def_x32;
+ case SCMP_ARCH_ARM:
+ return &arch_def_arm;
+ }
+
+ return NULL;
+}
+
+/**
+ * Determine the maximum number of syscall arguments
+ * @param arch the architecture definition
+ *
+ * Determine the maximum number of syscall arguments for the given architecture.
+ * Returns the number of arguments on success, negative values on failure.
+ *
+ */
+int arch_arg_count_max(const struct arch_def *arch)
+{
+ switch (arch->token) {
+ case SCMP_ARCH_X86:
+ return x86_arg_count_max;
+ case SCMP_ARCH_X86_64:
+ return x86_64_arg_count_max;
+ case SCMP_ARCH_X32:
+ return x32_arg_count_max;
+ case SCMP_ARCH_ARM:
+ return arm_arg_count_max;
+ }
+
+ return -EDOM;
+}
+
+/**
+ * Determine the argument offset for the lower 32 bits
+ * @param arch the architecture definition
+ * @param arg the argument number
+ *
+ * Determine the correct offset for the low 32 bits of the given argument based
+ * on the architecture definition. Returns the offset on success, negative
+ * values on failure.
+ *
+ */
+int arch_arg_offset_lo(const struct arch_def *arch, unsigned int arg)
+{
+ switch (arch->token) {
+ case SCMP_ARCH_X86_64:
+ return x86_64_arg_offset_lo(arg);
+ default:
+ return -EDOM;
+ }
+}
+
+/**
+ * Determine the argument offset for the high 32 bits
+ * @param arch the architecture definition
+ * @param arg the argument number
+ *
+ * Determine the correct offset for the high 32 bits of the given argument
+ * based on the architecture definition. Returns the offset on success,
+ * negative values on failure.
+ *
+ */
+int arch_arg_offset_hi(const struct arch_def *arch, unsigned int arg)
+{
+ switch (arch->token) {
+ case SCMP_ARCH_X86_64:
+ return x86_64_arg_offset_hi(arg);
+ default:
+ return -EDOM;
+ }
+}
+
+/**
+ * Resolve a syscall name to a number
+ * @param arch the architecture definition
+ * @param name the syscall name
+ *
+ * Resolve the given syscall name to the syscall number based on the given
+ * architecture. Returns the syscall number on success, including negative
+ * pseudo syscall numbers; returns __NR_SCMP_ERROR on failure.
+ *
+ */
+int arch_syscall_resolve_name(const struct arch_def *arch, const char *name)
+{
+ switch (arch->token) {
+ case SCMP_ARCH_X86:
+ return x86_syscall_resolve_name(name);
+ case SCMP_ARCH_X86_64:
+ return x86_64_syscall_resolve_name(name);
+ case SCMP_ARCH_X32:
+ return x32_syscall_resolve_name(name);
+ case SCMP_ARCH_ARM:
+ return arm_syscall_resolve_name(name);
+ }
+
+ return __NR_SCMP_ERROR;
+}
+
+/**
+ * Resolve a syscall number to a name
+ * @param arch the architecture definition
+ * @param num the syscall number
+ *
+ * Resolve the given syscall number to the syscall name based on the given
+ * architecture. Returns a pointer to the syscall name string on success,
+ * including pseudo syscall names; returns NULL on failure.
+ *
+ */
+const char *arch_syscall_resolve_num(const struct arch_def *arch, int num)
+{
+ switch (arch->token) {
+ case SCMP_ARCH_X86:
+ return x86_syscall_resolve_num(num);
+ case SCMP_ARCH_X86_64:
+ return x86_64_syscall_resolve_num(num);
+ case SCMP_ARCH_X32:
+ return x32_syscall_resolve_num(num);
+ case SCMP_ARCH_ARM:
+ return arm_syscall_resolve_num(num);
+ }
+
+ return NULL;
+}
+
+/**
+ * Translate the syscall number
+ * @param arch the architecture definition
+ * @param syscall the syscall number
+ *
+ * Translate the syscall number, in the context of the native architecure, to
+ * the provided architecure. Returns zero on success, negative values on
+ * failure.
+ *
+ */
+int arch_syscall_translate(const struct arch_def *arch, int *syscall)
+{
+ int sc_num;
+ const char *sc_name;
+
+ if (arch->token != arch_def_native->token) {
+ sc_name = arch_syscall_resolve_num(arch_def_native, *syscall);
+ if (sc_name == NULL)
+ return -EFAULT;
+
+ sc_num = arch_syscall_resolve_name(arch, sc_name);
+ if (sc_num == __NR_SCMP_ERROR)
+ return -EFAULT;
+
+ *syscall = sc_num;
+ }
+
+ return 0;
+}
+
+/**
+ * Rewrite a syscall value to match the architecture
+ * @param arch the architecture definition
+ * @param strict strict flag
+ * @param syscall the syscall number
+ *
+ * Syscalls can vary across different architectures so this function rewrites
+ * the syscall into the correct value for the specified architecture. If
+ * @strict is true then the function will fail if the syscall can not be
+ * preservered, however, if @strict is false the function will do a "best
+ * effort" rewrite and not fail. Returns zero on success, negative values on
+ * failure.
+ *
+ */
+int arch_syscall_rewrite(const struct arch_def *arch, bool strict, int *syscall)
+{
+ int sys = *syscall;
+
+ if (sys >= 0) {
+ /* we shouldn't be here - no rewrite needed */
+ return 0;
+ } else if (sys < 0 && sys > -100) {
+ /* reserved values */
+ return -EINVAL;
+ } else if (sys <= -100 && sys > -10000) {
+ /* rewritable syscalls */
+ switch (arch->token) {
+ case SCMP_ARCH_X86:
+ return x86_syscall_rewrite(arch, strict, syscall);
+ }
+ /* NOTE: we fall through to the default handling (strict?) if
+ * we don't support any rewriting for the architecture */
+ }
+
+ /* syscalls not defined on this architecture */
+ if (strict)
+ return -EDOM;
+ return 0;
+}
+
+/**
+ * Rewrite a filter rule to match the architecture specifics
+ * @param arch the architecture definition
+ * @param strict strict flag
+ * @param syscall the syscall number
+ * @param chain the argument filter chain
+ *
+ * Syscalls can vary across different architectures so this function handles
+ * the necessary seccomp rule rewrites to ensure the right thing is done
+ * regardless of the rule or architecture. If @strict is true then the
+ * function will fail if the entire filter can not be preservered, however,
+ * if @strict is false the function will do a "best effort" rewrite and not
+ * fail. Returns zero on success, negative values on failure.
+ *
+ */
+int arch_filter_rewrite(const struct arch_def *arch,
+ bool strict, int *syscall, struct db_api_arg *chain)
+{
+ int sys = *syscall;
+
+ if (sys >= 0) {
+ /* we shouldn't be here - no rewrite needed */
+ return 0;
+ } else if (sys < 0 && sys > -100) {
+ /* reserved values */
+ return -EINVAL;
+ } else if (sys <= -100 && sys > -10000) {
+ /* rewritable syscalls */
+ switch (arch->token) {
+ case SCMP_ARCH_X86:
+ return x86_filter_rewrite(arch, strict, syscall, chain);
+ }
+ /* NOTE: we fall through to the default handling (strict?) if
+ * we don't support any rewriting for the architecture */
+ }
+
+ /* syscalls not defined on this architecture */
+ if (strict)
+ return -EDOM;
+ return 0;
+}
--- /dev/null
+/**
+ * Enhanced Seccomp Architecture/Machine Specific Code
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _ARCH_H
+#define _ARCH_H
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <seccomp.h>
+
+#include "system.h"
+
+struct db_api_arg;
+
+struct arch_def {
+ uint32_t token;
+ uint32_t token_bpf;
+ enum {
+ ARCH_SIZE_UNSPEC = 0,
+ ARCH_SIZE_32 = 32,
+ ARCH_SIZE_64 = 64,
+ } size;
+ enum {
+ ARCH_ENDIAN_UNSPEC = 0,
+ ARCH_ENDIAN_LITTLE,
+ ARCH_ENDIAN_BIG,
+ } endian;
+};
+
+/* arch_def for the current architecture */
+extern const struct arch_def *arch_def_native;
+
+/* NOTE: Syscall mappings can be found by running the following commands
+ * on the specific architecture's include file:
+ * # gcc -E -dM <file> | grep '__NR_'
+ * where <file> in many cases is /usr/include/asm/unistd.h, however,
+ * depending on the architecture you may need to use a different header.
+ * Further, you can automatically format this list for use as a struct
+ * initializer with the following command:
+ * # gcc -E -dM <file> | grep '__NR_' | \
+ * sed -e 's/#define[ \t]\+__NR_//' | sort | \
+ * sed -e 's/\([^ \t]\+\)\([ \t]\+\)\([0-9]\+\)/\t{ \"\1\", \3 },/'
+ * Finally, when creating a table/array of this structure, the final
+ * sentinel entry should be "{ NULL, __NR_SCMP_ERROR }"; see the existing
+ * tables as an example.
+ */
+struct arch_syscall_def {
+ const char *name;
+ unsigned int num;
+};
+
+#define DATUM_MAX ((scmp_datum_t)-1)
+#define D64_LO(x) ((uint32_t)((uint64_t)(x) & 0x00000000ffffffff))
+#define D64_HI(x) ((uint32_t)((uint64_t)(x) >> 32))
+
+#define ARG_COUNT_MAX 6
+
+int arch_valid(uint32_t arch);
+
+const struct arch_def *arch_def_lookup(uint32_t token);
+
+int arch_arg_count_max(const struct arch_def *arch);
+
+/**
+ * Determine the argument offset
+ * @param _arg the argument number
+ *
+ * Return the correct offset of the given argument.
+ *
+ */
+#define arch_arg_offset(_arg) (offsetof(struct seccomp_data, args[_arg]))
+
+int arch_arg_offset_lo(const struct arch_def *arch, unsigned int arg);
+int arch_arg_offset_hi(const struct arch_def *arch, unsigned int arg);
+
+int arch_syscall_resolve_name(const struct arch_def *arch, const char *name);
+const char *arch_syscall_resolve_num(const struct arch_def *arch, int num);
+
+int arch_syscall_translate(const struct arch_def *arch, int *syscall);
+int arch_syscall_rewrite(const struct arch_def *arch, bool strict,
+ int *syscall);
+
+int arch_filter_rewrite(const struct arch_def *arch,
+ bool strict, int *syscall, struct db_api_arg *chain);
+
+#endif
--- /dev/null
+/**
+ * Enhanced Seccomp Filter DB
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+#include "db.h"
+
+/* state values */
+#define _DB_STA_VALID 0xA1B2C3D4
+#define _DB_STA_FREED 0x1A2B3C4D
+
+/* the priority field is fairly simple - without any user hints, or in the case
+ * of a hint "tie", we give higher priority to syscalls with less chain nodes
+ * (filter is easier to evaluate) */
+#define _DB_PRI_MASK_CHAIN 0x0000FFFF
+#define _DB_PRI_MASK_USER 0x00FF0000
+#define _DB_PRI_USER(x) (((x) << 16) & _DB_PRI_MASK_USER)
+
+/* private structure for tracking the state of the sub-tree "pruning" */
+struct db_prune_state {
+ bool prefix_exist;
+ bool prefix_new;
+ bool matched;
+};
+
+static unsigned int _db_tree_free(struct db_arg_chain_tree *tree);
+
+/**
+ * Do not call this function directly, use _db_tree_free() instead
+ */
+static unsigned int __db_tree_free(struct db_arg_chain_tree *tree)
+{
+ int cnt;
+
+ if (tree == NULL || --(tree->refcnt) > 0)
+ return 0;
+
+ /* we assume the caller has ensured that 'tree->lvl_prv == NULL' */
+ cnt = __db_tree_free(tree->lvl_nxt);
+ cnt += _db_tree_free(tree->nxt_t);
+ cnt += _db_tree_free(tree->nxt_f);
+
+ free(tree);
+ return cnt + 1;
+}
+
+/**
+ * Free a syscall filter argument chain tree
+ * @param list the argument chain list
+ *
+ * This function frees a syscall argument chain list and returns the number of
+ * nodes freed.
+ *
+ */
+static unsigned int _db_tree_free(struct db_arg_chain_tree *tree)
+{
+ struct db_arg_chain_tree *iter;
+
+ if (tree == NULL)
+ return 0;
+
+ iter = tree;
+ while (iter->lvl_prv != NULL)
+ iter = iter->lvl_prv;
+
+ return __db_tree_free(iter);
+}
+
+/**
+ * Remove a node from an argument chain tree
+ * @param tree the pointer to the tree
+ * @param node the node to remove
+ *
+ * This function searches the tree looking for the node and removes it once
+ * found. Returns the number of nodes freed.
+ *
+ */
+static unsigned int _db_tree_remove(struct db_arg_chain_tree **tree,
+ struct db_arg_chain_tree *node)
+{
+ int cnt = 0;
+ struct db_arg_chain_tree *c_iter;
+
+ if (tree == NULL || *tree == NULL || node == NULL)
+ return 0;
+
+ c_iter = *tree;
+ while (c_iter->lvl_prv != NULL)
+ c_iter = c_iter->lvl_prv;
+
+ do {
+ if (c_iter == node || db_chain_zombie(c_iter)) {
+ /* remove from the tree */
+ if (c_iter == *tree) {
+ if (c_iter->lvl_prv != NULL)
+ *tree = c_iter->lvl_prv;
+ else
+ *tree = c_iter->lvl_nxt;
+ }
+ if (c_iter->lvl_prv != NULL)
+ c_iter->lvl_prv->lvl_nxt = c_iter->lvl_nxt;
+ if (c_iter->lvl_nxt != NULL)
+ c_iter->lvl_nxt->lvl_prv = c_iter->lvl_prv;
+
+ /* free and return */
+ c_iter->lvl_prv = NULL;
+ c_iter->lvl_nxt = NULL;
+ cnt += _db_tree_free(c_iter);
+ return cnt;
+ }
+
+ /* check the true/false sub-trees */
+ cnt += _db_tree_remove(&(c_iter->nxt_t), node);
+ cnt += _db_tree_remove(&(c_iter->nxt_f), node);
+
+ c_iter = c_iter->lvl_nxt;
+ } while (c_iter != NULL);
+
+ return cnt;
+}
+
+/**
+ * Traverse a tree checking the action values
+ * @param tree the pointer to the tree
+ * @param action the action
+ *
+ * Traverse the tree inspecting each action to see if it matches the given
+ * action. Returns zero if all actions match the given action, negative values
+ * on failure.
+ *
+ */
+static int _db_tree_act_check(struct db_arg_chain_tree *tree, uint32_t action)
+{
+ int rc;
+ struct db_arg_chain_tree *c_iter;
+
+ if (tree == NULL)
+ return 0;
+
+ c_iter = tree;
+ while (c_iter->lvl_prv != NULL)
+ c_iter = c_iter->lvl_prv;
+
+ do {
+ if (c_iter->act_t_flg && c_iter->act_t != action)
+ return -EEXIST;
+ if (c_iter->act_f_flg && c_iter->act_f != action)
+ return -EEXIST;
+
+ rc = _db_tree_act_check(c_iter->nxt_t, action);
+ if (rc < 0)
+ return rc;
+ rc = _db_tree_act_check(c_iter->nxt_f, action);
+ if (rc < 0)
+ return rc;
+
+ c_iter = c_iter->lvl_nxt;
+ } while (c_iter != NULL);
+
+ return 0;
+}
+
+/**
+ * Checks for a sub-tree match in an existing tree and prunes the tree
+ * @param prev the head of the existing tree or sub-tree
+ * @param existing the starting point into the existing tree
+ * @param new pointer to the new tree
+ * @param state pointer to the pruning state
+ *
+ * This function searches the existing and new trees trying to prune each to
+ * eliminate redundancy. Returns the number of nodes removed from the tree on
+ * success, zero if no changes were made, and negative values if the new tree
+ * should be discarded.
+ *
+ */
+static int _db_tree_sub_prune(struct db_arg_chain_tree **prev,
+ struct db_arg_chain_tree *existing,
+ struct db_arg_chain_tree *new,
+ struct db_prune_state *state)
+{
+ int rc = 0;
+ int rc_tmp;
+ struct db_arg_chain_tree *ec_iter;
+ struct db_arg_chain_tree *ec_iter_tmp;
+ struct db_arg_chain_tree *c_iter;
+ struct db_prune_state state_new;
+
+ if (!state || !existing || !new)
+ return 0;
+
+ ec_iter = existing;
+ c_iter = new;
+ do {
+ if (db_chain_eq(ec_iter, c_iter)) {
+ /* equal */
+
+ if (db_chain_leaf(c_iter)) {
+ /* leaf */
+ if (db_chain_eq_result(ec_iter, c_iter)) {
+ /* identical results */
+ if (prev != NULL)
+ return _db_tree_remove(prev,
+ ec_iter);
+ else
+ return -1;
+ }
+ if (c_iter->act_t_flg && ec_iter->nxt_t) {
+ /* new is shorter (true) */
+ if (prev == NULL)
+ return -1;
+ rc += _db_tree_remove(&(ec_iter->nxt_t),
+ ec_iter->nxt_t);
+ ec_iter->act_t = c_iter->act_t;
+ ec_iter->act_t_flg = true;
+ }
+ if (c_iter->act_f_flg && ec_iter->nxt_f) {
+ /* new is shorter (false) */
+ if (prev == NULL)
+ return -1;
+ rc += _db_tree_remove(&(ec_iter->nxt_f),
+ ec_iter->nxt_f);
+ ec_iter->act_f = c_iter->act_f;
+ ec_iter->act_f_flg = true;
+ }
+
+ return rc;
+ }
+
+ if (c_iter->nxt_t && ec_iter->act_t_flg)
+ /* existing is shorter (true) */
+ return -1;
+ if (c_iter->nxt_f && ec_iter->act_f_flg)
+ /* existing is shorter (false) */
+ return -1;
+
+ if (c_iter->nxt_t) {
+ state_new = *state;
+ state_new.matched = true;
+ rc_tmp = _db_tree_sub_prune((prev ?
+ &ec_iter : NULL),
+ ec_iter->nxt_t,
+ c_iter->nxt_t,
+ &state_new);
+ rc += (rc_tmp > 0 ? rc_tmp : 0);
+ if (state->prefix_new && rc_tmp < 0)
+ return (rc > 0 ? rc : rc_tmp);
+ }
+ if (c_iter->nxt_f) {
+ state_new = *state;
+ state_new.matched = true;
+ rc_tmp = _db_tree_sub_prune((prev ?
+ &ec_iter : NULL),
+ ec_iter->nxt_f,
+ c_iter->nxt_f,
+ &state_new);
+ rc += (rc_tmp > 0 ? rc_tmp : 0);
+ if (state->prefix_new && rc_tmp < 0)
+ return (rc > 0 ? rc : rc_tmp);
+ }
+ } else if (db_chain_lt(ec_iter, c_iter)) {
+ /* less than */
+ if (state->matched || state->prefix_new)
+ goto next;
+ state_new = *state;
+ state_new.prefix_exist = true;
+
+ if (ec_iter->nxt_t) {
+ rc_tmp = _db_tree_sub_prune((prev ?
+ &ec_iter : NULL),
+ ec_iter->nxt_t,
+ c_iter,
+ &state_new);
+ rc += (rc_tmp > 0 ? rc_tmp : 0);
+ }
+ if (ec_iter->nxt_f) {
+ rc_tmp = _db_tree_sub_prune((prev ?
+ &ec_iter : NULL),
+ ec_iter->nxt_f,
+ c_iter,
+ &state_new);
+ rc += (rc_tmp > 0 ? rc_tmp : 0);
+ }
+ } else if (db_chain_gt(ec_iter, c_iter)) {
+ /* greater than */
+ if (state->matched || state->prefix_exist)
+ goto next;
+ state_new = *state;
+ state_new.prefix_new = true;
+
+ if (c_iter->nxt_t) {
+ rc_tmp = _db_tree_sub_prune(NULL,
+ ec_iter,
+ c_iter->nxt_t,
+ &state_new);
+ rc += (rc_tmp > 0 ? rc_tmp : 0);
+ if (rc_tmp < 0)
+ return (rc > 0 ? rc : rc_tmp);
+ }
+ if (c_iter->nxt_f) {
+ rc_tmp = _db_tree_sub_prune(NULL,
+ ec_iter,
+ c_iter->nxt_f,
+ &state_new);
+ rc += (rc_tmp > 0 ? rc_tmp : 0);
+ if (rc_tmp < 0)
+ return (rc > 0 ? rc : rc_tmp);
+ }
+ }
+
+next:
+ /* re-check current node and advance to the next node */
+ if (db_chain_zombie(ec_iter)) {
+ ec_iter_tmp = ec_iter->lvl_nxt;
+ rc += _db_tree_remove(prev, ec_iter);
+ ec_iter = ec_iter_tmp;
+ } else
+ ec_iter = ec_iter->lvl_nxt;
+ } while (ec_iter);
+
+ return rc;
+}
+
+/**
+ * Validate the seccomp action
+ * @param action the seccomp action
+ *
+ * Verify that the given action is a valid seccomp action; return zero if
+ * valid, -EINVAL if invalid.
+ */
+int db_action_valid(uint32_t action)
+{
+ if (action == SCMP_ACT_KILL)
+ return 0;
+ else if (action == SCMP_ACT_TRAP)
+ return 0;
+ else if (action == SCMP_ACT_ERRNO(action & 0x0000ffff))
+ return 0;
+ else if (action == SCMP_ACT_TRACE(action & 0x0000ffff))
+ return 0;
+ else if (action == SCMP_ACT_ALLOW)
+ return 0;
+
+ return -EINVAL;
+}
+
+/**
+ * Free and reset the seccomp filter collection
+ * @param col the seccomp filter collection
+ * @param def_action the default filter action
+ *
+ * This function frees any existing filter DBs and resets the collection to a
+ * default state.
+ *
+ */
+void db_col_reset(struct db_filter_col *col, uint32_t def_action)
+{
+ unsigned int iter;
+
+ if (col == NULL)
+ return;
+
+ /* free any filters */
+ for (iter = 0; iter < col->filter_cnt; iter++)
+ db_release(col->filters[iter]);
+ col->filter_cnt = 0;
+ free(col->filters);
+ col->filters = NULL;
+
+ /* set the default attribute values */
+ col->attr.act_default = def_action;
+ col->attr.act_badarch = SCMP_ACT_KILL;
+ col->attr.nnp_enable = 1;
+
+ /* set the state */
+ col->state = _DB_STA_VALID;
+}
+
+/**
+ * Intitalize a seccomp filter collection
+ * @param def_action the default filter action
+ *
+ * This function initializes a seccomp filter collection and readies it for
+ * use. Returns a pointer to the collection on success, NULL on failure.
+ *
+ */
+struct db_filter_col *db_col_init(uint32_t def_action)
+{
+ struct db_filter_col *col;
+
+ col = malloc(sizeof(*col));
+ if (col == NULL)
+ return NULL;
+
+ /* clear the buffer for the first time */
+ memset(col, 0, sizeof(*col));
+
+ /* reset the DB to a known state */
+ db_col_reset(col, def_action);
+
+ return col;
+}
+
+/**
+ * Destroy a seccomp filter collection
+ * @param col the seccomp filter collection
+ *
+ * This function destroys a seccomp filter collection. After calling this
+ * function, the filter should no longer be referenced.
+ *
+ */
+void db_col_release(struct db_filter_col *col)
+{
+ if (col == NULL)
+ return;
+
+ /* set the state, just in case */
+ col->state = _DB_STA_FREED;
+
+ /* free and reset the DB */
+ db_col_reset(col, 0);
+ free(col);
+}
+
+/**
+ * Validate a filter collection
+ * @param col the seccomp filter collection
+ *
+ * This function validates a seccomp filter collection. Returns zero if the
+ * collection is valid, negative values on failure.
+ *
+ */
+int db_col_valid(struct db_filter_col *col)
+{
+ if (col != NULL && col->state == _DB_STA_VALID)
+ return 0;
+ return -EINVAL;
+}
+
+/**
+ * Merge two filter collections
+ * @param col_dst the destination filter collection
+ * @param col_src the source filter collection
+ *
+ * This function merges two filter collections into the given destination
+ * collection. The source filter collection is no longer valid if the function
+ * returns successfully. Returns zero on success, negative values on failure.
+ *
+ */
+int db_col_merge(struct db_filter_col *col_dst, struct db_filter_col *col_src)
+{
+ unsigned int iter_a, iter_b;
+ struct db_filter **dbs;
+
+ /* make sure we don't have any arch/filter collisions */
+ for (iter_a = 0; iter_a < col_dst->filter_cnt; iter_a++) {
+ for (iter_b = 0; iter_b < col_src->filter_cnt; iter_b++) {
+ if (col_dst->filters[iter_a]->arch->token ==
+ col_src->filters[iter_b]->arch->token)
+ return -EEXIST;
+ }
+ }
+
+ /* expand the destination */
+ dbs = realloc(col_dst->filters,
+ sizeof(struct db_filter *) *
+ (col_dst->filter_cnt + col_src->filter_cnt));
+ if (dbs == NULL)
+ return -ENOMEM;
+ col_dst->filters = dbs;
+
+ /* transfer the architecture filters */
+ for (iter_a = col_dst->filter_cnt, iter_b = 0;
+ iter_b < col_src->filter_cnt; iter_a++, iter_b++) {
+ col_dst->filters[iter_a] = col_src->filters[iter_b];
+ col_dst->filter_cnt++;
+ }
+
+ /* free the source */
+ col_src->filter_cnt = 0;
+ db_col_release(col_src);
+
+ return 0;
+}
+
+/**
+ * Check to see if an architecture filter exists in the filter collection
+ * @param col the seccomp filter collection
+ * @param arch_token the architecture token
+ *
+ * Iterate through the given filter collection checking to see if a filter
+ * exists for the specified architecture. Returns -EEXIST if a filter is found,
+ * zero if a matching filter does not exist.
+ *
+ */
+int db_col_arch_exist(struct db_filter_col *col, uint32_t arch_token)
+{
+ unsigned int iter;
+
+ for (iter = 0; iter < col->filter_cnt; iter++)
+ if (col->filters[iter]->arch->token == arch_token)
+ return -EEXIST;
+
+ return 0;
+}
+
+/**
+ * Get a filter attribute
+ * @param col the seccomp filter collection
+ * @param attr the filter attribute
+ * @param value the filter attribute value
+ *
+ * Get the requested filter attribute and provide it via @value. Returns zero
+ * on success, negative values on failure.
+ *
+ */
+int db_col_attr_get(const struct db_filter_col *col,
+ enum scmp_filter_attr attr, uint32_t *value)
+{
+ int rc = 0;
+
+ switch (attr) {
+ case SCMP_FLTATR_ACT_DEFAULT:
+ *value = col->attr.act_default;
+ break;
+ case SCMP_FLTATR_ACT_BADARCH:
+ *value = col->attr.act_badarch;
+ break;
+ case SCMP_FLTATR_CTL_NNP:
+ *value = col->attr.nnp_enable;
+ break;
+ default:
+ rc = -EEXIST;
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * Set a filter attribute
+ * @param db the seccomp filter collection
+ * @param attr the filter attribute
+ * @param value the filter attribute value
+ *
+ * Set the requested filter attribute with the given value. Returns zero on
+ * success, negative values on failure.
+ *
+ */
+int db_col_attr_set(struct db_filter_col *col,
+ enum scmp_filter_attr attr, uint32_t value)
+{
+ int rc = 0;
+
+ switch (attr) {
+ case SCMP_FLTATR_ACT_DEFAULT:
+ /* read only */
+ return -EACCES;
+ break;
+ case SCMP_FLTATR_ACT_BADARCH:
+ if (db_action_valid(value) == 0)
+ col->attr.act_badarch = value;
+ else
+ return -EINVAL;
+ break;
+ case SCMP_FLTATR_CTL_NNP:
+ col->attr.nnp_enable = (value ? 1 : 0);
+ break;
+ default:
+ rc = -EEXIST;
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * Add a new filter DB to a filter collection
+ * @param col the seccomp filter collection
+ * @param db the seccomp filter DB
+ *
+ * This function adds an existing seccomp filter DB to an existing seccomp
+ * filter collection assuming there isn't a filter DB already present with the
+ * same architecture. Returns zero on success, negative values on failure.
+ *
+ */
+int db_col_db_add(struct db_filter_col *col, struct db_filter *db)
+{
+ struct db_filter **dbs;
+
+ if (db_col_arch_exist(col, db->arch->token))
+ return -EEXIST;
+
+ dbs = realloc(col->filters,
+ sizeof(struct db_filter *) * (col->filter_cnt + 1));
+ if (dbs == NULL)
+ return -ENOMEM;
+ col->filters = dbs;
+ col->filter_cnt++;
+ col->filters[col->filter_cnt - 1] = db;
+
+ return 0;
+}
+
+/**
+ * Remove a filter DB from a filter collection
+ * @param col the seccomp filter collection
+ * @param arch_token the architecture token
+ *
+ * This function removes an existing seccomp filter DB from an existing seccomp
+ * filter collection. Returns zero on success, negative values on failure.
+ *
+ */
+int db_col_db_remove(struct db_filter_col *col, uint32_t arch_token)
+{
+ unsigned int iter;
+ unsigned int found;
+ struct db_filter **dbs;
+
+ if ((col->filter_cnt <= 1) || (db_col_arch_exist(col, arch_token) == 0))
+ return -EINVAL;
+
+ for (found = 0, iter = 0; iter < col->filter_cnt; iter++) {
+ if (found)
+ col->filters[iter - 1] = col->filters[iter];
+ else if (col->filters[iter]->arch->token == arch_token) {
+ db_release(col->filters[iter]);
+ found = 1;
+ }
+ }
+ col->filters[--col->filter_cnt] = NULL;
+
+ /* NOTE: if we can't do the realloc it isn't fatal, we just have some
+ * extra space that will get cleaned up later */
+ dbs = realloc(col->filters,
+ sizeof(struct db_filter *) * col->filter_cnt);
+ if (dbs != NULL)
+ col->filters = dbs;
+
+ return 0;
+}
+
+/**
+ * Free and reset the seccomp filter DB
+ * @param db the seccomp filter DB
+ * @param def_action the default filter action
+ *
+ * This function frees any existing filters and resets the filter DB to a
+ * default state; only the DB architecture is preserved.
+ *
+ */
+void db_reset(struct db_filter *db)
+{
+ struct db_sys_list *s_iter;
+
+ if (db == NULL)
+ return;
+
+ /* free any filters */
+ if (db->syscalls != NULL) {
+ s_iter = db->syscalls;
+ while (s_iter != NULL) {
+ db->syscalls = s_iter->next;
+ _db_tree_free(s_iter->chains);
+ free(s_iter);
+ s_iter = db->syscalls;
+ }
+ db->syscalls = NULL;
+ }
+}
+
+/**
+ * Intitalize a seccomp filter DB
+ * @param arch the architecture definition
+ *
+ * This function initializes a seccomp filter DB and readies it for use.
+ * Returns a pointer to the DB on success, NULL on failure.
+ *
+ */
+struct db_filter *db_init(const struct arch_def *arch)
+{
+ struct db_filter *db;
+
+ db = malloc(sizeof(*db));
+ if (db == NULL)
+ return NULL;
+
+ /* clear the buffer for the first time and set the arch */
+ memset(db, 0, sizeof(*db));
+ db->arch = arch;
+
+ /* reset the DB to a known state */
+ db_reset(db);
+
+ return db;
+}
+
+/**
+ * Destroy a seccomp filter DB
+ * @param db the seccomp filter DB
+ *
+ * This function destroys a seccomp filter DB. After calling this function,
+ * the filter should no longer be referenced.
+ *
+ */
+void db_release(struct db_filter *db)
+{
+ if (db == NULL)
+ return;
+
+ /* free and reset the DB */
+ db_reset(db);
+ free(db);
+}
+
+/**
+ * Update the user specified portion of the syscall priority
+ * @param db the seccomp filter db
+ * @param syscall the syscall number
+ * @param priority the syscall priority
+ *
+ * This function sets, or updates, the syscall priority; the highest priority
+ * value between the existing and specified value becomes the new syscall
+ * priority. If the syscall entry does not already exist, a new phantom
+ * syscall entry is created as a placeholder. Returns zero on success,
+ * negative values on failure.
+ *
+ */
+int db_syscall_priority(struct db_filter *db,
+ unsigned int syscall, uint8_t priority)
+{
+ unsigned int sys_pri = _DB_PRI_USER(priority);
+ struct db_sys_list *s_new, *s_iter, *s_prev = NULL;
+
+ assert(db != NULL);
+
+ s_iter = db->syscalls;
+ while (s_iter != NULL && s_iter->num < syscall) {
+ s_prev = s_iter;
+ s_iter = s_iter->next;
+ }
+
+ /* matched an existing syscall entry */
+ if (s_iter != NULL && s_iter->num == syscall) {
+ if (sys_pri > (s_iter->priority & _DB_PRI_MASK_USER)) {
+ s_iter->priority &= (~_DB_PRI_MASK_USER);
+ s_iter->priority |= sys_pri;
+ }
+ return 0;
+ }
+
+ /* no existing syscall entry - create a phantom entry */
+ s_new = malloc(sizeof(*s_new));
+ if (s_new == NULL)
+ return -ENOMEM;
+ memset(s_new, 0, sizeof(*s_new));
+ s_new->num = syscall;
+ s_new->priority = sys_pri;
+ s_new->valid = false;
+
+ /* add it before s_iter */
+ if (s_prev != NULL) {
+ s_new->next = s_prev->next;
+ s_prev->next = s_new;
+ } else {
+ s_new->next = db->syscalls;
+ db->syscalls = s_new;
+ }
+
+ return 0;
+}
+
+/**
+ * Fixup the node based on the op/mask
+ * @param node the chain node
+ *
+ * Apply some simplifications based on the comparison op and mask value.
+ *
+ */
+static void _db_node_mask_fixup(struct db_arg_chain_tree *node)
+{
+ if (node->op == SCMP_CMP_MASKED_EQ && node->mask == 0) {
+ node->op = SCMP_CMP_EQ;
+ node->mask = ARG_MASK_MAX;
+ node->datum = 0;
+ } else
+ node->datum &= node->mask;
+}
+
+/**
+ * Generate a new filter rule for a 64 bit system
+ * @param arch the architecture definition
+ * @param action the filter action
+ * @param syscall the syscall number
+ * @param chain argument filter chain
+ *
+ * This function generates a new syscall filter for a 64 bit system. Returns
+ * zero on success, negative values on failure.
+ *
+ */
+static struct db_sys_list *_db_rule_gen_64(const struct arch_def *arch,
+ uint32_t action,
+ unsigned int syscall,
+ struct db_api_arg *chain)
+{
+ unsigned int iter;
+ int chain_len_max;
+ struct db_sys_list *s_new;
+ struct db_arg_chain_tree *c_iter_hi = NULL, *c_iter_lo = NULL;
+ struct db_arg_chain_tree *c_prev_hi = NULL, *c_prev_lo = NULL;
+ bool tf_flag;
+
+ s_new = malloc(sizeof(*s_new));
+ if (s_new == NULL)
+ return NULL;
+ memset(s_new, 0, sizeof(*s_new));
+ s_new->num = syscall;
+ s_new->valid = true;
+ /* run through the argument chain */
+ chain_len_max = arch_arg_count_max(arch);
+ for (iter = 0; iter < chain_len_max; iter++) {
+ if (chain[iter].valid == 0)
+ continue;
+
+ c_iter_hi = malloc(sizeof(*c_iter_hi));
+ if (c_iter_hi == NULL)
+ goto gen_64_failure;
+ memset(c_iter_hi, 0, sizeof(*c_iter_hi));
+ c_iter_hi->refcnt = 1;
+ c_iter_lo = malloc(sizeof(*c_iter_lo));
+ if (c_iter_lo == NULL) {
+ free(c_iter_hi);
+ goto gen_64_failure;
+ }
+ memset(c_iter_lo, 0, sizeof(*c_iter_lo));
+ c_iter_lo->refcnt = 1;
+
+ /* link this level to the previous level */
+ if (c_prev_lo != NULL) {
+ if (!tf_flag) {
+ c_prev_lo->nxt_f = c_iter_hi;
+ c_prev_hi->nxt_f = c_iter_hi;
+ c_iter_hi->refcnt++;
+ } else
+ c_prev_lo->nxt_t = c_iter_hi;
+ } else
+ s_new->chains = c_iter_hi;
+ s_new->node_cnt += 2;
+
+ /* set the arg, op, and datum fields */
+ c_iter_hi->arg = chain[iter].arg;
+ c_iter_lo->arg = chain[iter].arg;
+ c_iter_hi->arg_offset = arch_arg_offset_hi(arch,
+ c_iter_hi->arg);
+ c_iter_lo->arg_offset = arch_arg_offset_lo(arch,
+ c_iter_lo->arg);
+ switch (chain[iter].op) {
+ case SCMP_CMP_GT:
+ c_iter_hi->op = SCMP_CMP_GE;
+ c_iter_lo->op = SCMP_CMP_GT;
+ tf_flag = true;
+ break;
+ case SCMP_CMP_NE:
+ c_iter_hi->op = SCMP_CMP_EQ;
+ c_iter_lo->op = SCMP_CMP_EQ;
+ tf_flag = false;
+ break;
+ case SCMP_CMP_LT:
+ c_iter_hi->op = SCMP_CMP_GE;
+ c_iter_lo->op = SCMP_CMP_GE;
+ tf_flag = false;
+ break;
+ case SCMP_CMP_LE:
+ c_iter_hi->op = SCMP_CMP_GE;
+ c_iter_lo->op = SCMP_CMP_GT;
+ tf_flag = false;
+ break;
+ default:
+ c_iter_hi->op = chain[iter].op;
+ c_iter_lo->op = chain[iter].op;
+ tf_flag = true;
+ }
+ c_iter_hi->mask = D64_HI(chain[iter].mask);
+ c_iter_lo->mask = D64_LO(chain[iter].mask);
+ c_iter_hi->datum = D64_HI(chain[iter].datum);
+ c_iter_lo->datum = D64_LO(chain[iter].datum);
+
+ /* fixup the mask/datum */
+ _db_node_mask_fixup(c_iter_hi);
+ _db_node_mask_fixup(c_iter_lo);
+
+ /* link the hi and lo chain nodes */
+ c_iter_hi->nxt_t = c_iter_lo;
+
+ c_prev_hi = c_iter_hi;
+ c_prev_lo = c_iter_lo;
+ }
+ if (c_iter_lo != NULL) {
+ /* set the leaf node */
+ if (!tf_flag) {
+ c_iter_lo->act_f_flg = true;
+ c_iter_lo->act_f = action;
+ c_iter_hi->act_f_flg = true;
+ c_iter_hi->act_f = action;
+ } else {
+ c_iter_lo->act_t_flg = true;
+ c_iter_lo->act_t = action;
+ }
+ } else
+ s_new->action = action;
+
+ return s_new;
+
+gen_64_failure:
+ /* free the new chain and its syscall struct */
+ _db_tree_free(s_new->chains);
+ free(s_new);
+ return NULL;
+}
+
+/**
+ * Generate a new filter rule for a 32 bit system
+ * @param arch the architecture definition
+ * @param action the filter action
+ * @param syscall the syscall number
+ * @param chain argument filter chain
+ *
+ * This function generates a new syscall filter for a 32 bit system. Returns
+ * zero on success, negative values on failure.
+ *
+ */
+static struct db_sys_list *_db_rule_gen_32(const struct arch_def *arch,
+ uint32_t action,
+ unsigned int syscall,
+ struct db_api_arg *chain)
+{
+ unsigned int iter;
+ int chain_len_max;
+ struct db_sys_list *s_new;
+ struct db_arg_chain_tree *c_iter = NULL, *c_prev = NULL;
+ bool tf_flag;
+
+ s_new = malloc(sizeof(*s_new));
+ if (s_new == NULL)
+ return NULL;
+ memset(s_new, 0, sizeof(*s_new));
+ s_new->num = syscall;
+ s_new->valid = true;
+ /* run through the argument chain */
+ chain_len_max = arch_arg_count_max(arch);
+ for (iter = 0; iter < chain_len_max; iter++) {
+ if (chain[iter].valid == 0)
+ continue;
+
+ c_iter = malloc(sizeof(*c_iter));
+ if (c_iter == NULL)
+ goto gen_32_failure;
+ memset(c_iter, 0, sizeof(*c_iter));
+ c_iter->refcnt = 1;
+ c_iter->arg = chain[iter].arg;
+ c_iter->arg_offset = arch_arg_offset(c_iter->arg);
+ c_iter->op = chain[iter].op;
+ c_iter->mask = chain[iter].mask;
+ c_iter->datum = chain[iter].datum;
+
+ /* link in the new node and update the chain */
+ if (c_prev != NULL) {
+ if (tf_flag)
+ c_prev->nxt_t = c_iter;
+ else
+ c_prev->nxt_f = c_iter;
+ } else
+ s_new->chains = c_iter;
+ s_new->node_cnt++;
+
+ /* rewrite the op to reduce the op/datum combos */
+ switch (c_iter->op) {
+ case SCMP_CMP_NE:
+ c_iter->op = SCMP_CMP_EQ;
+ tf_flag = false;
+ break;
+ case SCMP_CMP_LT:
+ c_iter->op = SCMP_CMP_GE;
+ tf_flag = false;
+ break;
+ case SCMP_CMP_LE:
+ c_iter->op = SCMP_CMP_GT;
+ tf_flag = false;
+ break;
+ default:
+ tf_flag = true;
+ }
+
+ /* fixup the mask/datum */
+ _db_node_mask_fixup(c_iter);
+
+ c_prev = c_iter;
+ }
+ if (c_iter != NULL) {
+ /* set the leaf node */
+ if (tf_flag) {
+ c_iter->act_t_flg = true;
+ c_iter->act_t = action;
+ } else {
+ c_iter->act_f_flg = true;
+ c_iter->act_f = action;
+ }
+ } else
+ s_new->action = action;
+
+ return s_new;
+
+gen_32_failure:
+ /* free the new chain and its syscall struct */
+ _db_tree_free(s_new->chains);
+ free(s_new);
+ return NULL;
+}
+
+/**
+ * Add a new rule to the seccomp filter DB
+ * @param db the seccomp filter db
+ * @param action the filter action
+ * @param syscall the syscall number
+ * @param chain argument filter chain
+ *
+ * This function adds a new syscall filter to the seccomp filter DB, adding to
+ * the existing filters for the syscall, unless no argument specific filters
+ * are present (filtering only on the syscall). When adding new chains, the
+ * shortest chain, or most inclusive filter match, will be entered into the
+ * filter DB. Returns zero on success, negative values on failure.
+ *
+ */
+int db_rule_add(struct db_filter *db, uint32_t action, unsigned int syscall,
+ struct db_api_arg *chain)
+{
+ int rc = -ENOMEM;
+ struct db_sys_list *s_new, *s_iter, *s_prev = NULL;
+ struct db_arg_chain_tree *c_iter = NULL, *c_prev = NULL;
+ struct db_arg_chain_tree *ec_iter;
+ struct db_prune_state state;
+ bool rm_flag = false;
+ unsigned int new_chain_cnt = 0;
+ unsigned int n_cnt;
+
+ assert(db != NULL);
+
+ /* do all our possible memory allocation up front so we don't have to
+ * worry about failure once we get to the point where we start updating
+ * the filter db */
+ if (db->arch->size == ARCH_SIZE_64)
+ s_new = _db_rule_gen_64(db->arch, action, syscall, chain);
+ else if (db->arch->size == ARCH_SIZE_32)
+ s_new = _db_rule_gen_32(db->arch, action, syscall, chain);
+ else
+ return -EFAULT;
+ if (s_new == NULL)
+ return -ENOMEM;
+ new_chain_cnt = s_new->node_cnt;
+
+ /* no more failures allowed after this point that would result in the
+ * stored filter being in an inconsistent state */
+
+ /* find a matching syscall/chain or insert a new one */
+ s_iter = db->syscalls;
+ while (s_iter != NULL && s_iter->num < syscall) {
+ s_prev = s_iter;
+ s_iter = s_iter->next;
+ }
+add_reset:
+ s_new->node_cnt = new_chain_cnt;
+ s_new->priority = _DB_PRI_MASK_CHAIN - s_new->node_cnt;
+ c_prev = NULL;
+ c_iter = s_new->chains;
+ if (s_iter != NULL)
+ ec_iter = s_iter->chains;
+ else
+ ec_iter = NULL;
+ if (s_iter == NULL || s_iter->num != syscall) {
+ /* new syscall, add before s_iter */
+ if (s_prev != NULL) {
+ s_new->next = s_prev->next;
+ s_prev->next = s_new;
+ } else {
+ s_new->next = db->syscalls;
+ db->syscalls = s_new;
+ }
+ return 0;
+ } else if (s_iter->chains == NULL) {
+ if (rm_flag || !s_iter->valid) {
+ /* we are here because our previous pass cleared the
+ * entire syscall chain when searching for a subtree
+ * match or the existing syscall entry is a phantom,
+ * so either way add the new chain */
+ s_iter->chains = s_new->chains;
+ s_iter->action = s_new->action;
+ s_iter->node_cnt = s_new->node_cnt;
+ if (s_iter->valid)
+ s_iter->priority = s_new->priority;
+ s_iter->valid = true;
+ free(s_new);
+ rc = 0;
+ goto add_priority_update;
+ } else
+ /* syscall exists without any chains - existing filter
+ * is at least as large as the new entry so cleanup and
+ * exit */
+ goto add_free_ok;
+ } else if (s_iter->chains != NULL && s_new->chains == NULL) {
+ /* syscall exists with chains but the new filter has no chains
+ * so we need to clear the existing chains and exit */
+ _db_tree_free(s_iter->chains);
+ s_iter->chains = NULL;
+ s_iter->node_cnt = 0;
+ s_iter->action = action;
+ goto add_free_ok;
+ }
+
+ /* check for sub-tree matches */
+ memset(&state, 0, sizeof(state));
+ rc = _db_tree_sub_prune(&(s_iter->chains), ec_iter, c_iter, &state);
+ if (rc > 0) {
+ rm_flag = true;
+ s_iter->node_cnt -= rc;
+ goto add_reset;
+ } else if (rc < 0)
+ goto add_free_ok;
+
+ /* syscall exists and has at least one existing chain - start at the
+ * top and walk the two chains */
+ do {
+ /* insert the new rule into the existing tree */
+ if (db_chain_eq(c_iter, ec_iter)) {
+ /* found a matching node on this chain level */
+ if (db_chain_action(c_iter) &&
+ db_chain_action(ec_iter)) {
+ /* both are "action" nodes */
+ if (c_iter->act_t_flg && ec_iter->act_t_flg) {
+ if (ec_iter->act_t != action)
+ goto add_free_exist;
+ } else if (c_iter->act_t_flg) {
+ ec_iter->act_t_flg = true;
+ ec_iter->act_t = action;
+ }
+ if (c_iter->act_f_flg && ec_iter->act_f_flg) {
+ if (ec_iter->act_f != action)
+ goto add_free_exist;
+ } else if (c_iter->act_f_flg) {
+ ec_iter->act_f_flg = true;
+ ec_iter->act_f = action;
+ }
+ if (ec_iter->act_t_flg == ec_iter->act_f_flg &&
+ ec_iter->act_t == ec_iter->act_f) {
+ n_cnt = _db_tree_remove(
+ &(s_iter->chains),
+ ec_iter);
+ s_iter->node_cnt -= n_cnt;
+ goto add_free_ok;
+ }
+ } else if (db_chain_action(c_iter)) {
+ /* new is shorter */
+ if (c_iter->act_t_flg) {
+ rc = _db_tree_act_check(ec_iter->nxt_t,
+ action);
+ if (rc < 0)
+ goto add_free;
+ n_cnt = _db_tree_free(ec_iter->nxt_t);
+ ec_iter->nxt_t = NULL;
+ ec_iter->act_t_flg = true;
+ ec_iter->act_t = action;
+ } else {
+ rc = _db_tree_act_check(ec_iter->nxt_f,
+ action);
+ if (rc < 0)
+ goto add_free;
+ n_cnt = _db_tree_free(ec_iter->nxt_f);
+ ec_iter->nxt_f = NULL;
+ ec_iter->act_f_flg = true;
+ ec_iter->act_f = action;
+ }
+ s_iter->node_cnt -= n_cnt;
+ }
+ if (c_iter->nxt_t != NULL) {
+ if (ec_iter->nxt_t != NULL) {
+ /* jump to the next level */
+ c_prev = c_iter;
+ c_iter = c_iter->nxt_t;
+ ec_iter = ec_iter->nxt_t;
+ s_new->node_cnt--;
+ } else if (ec_iter->act_t_flg) {
+ /* existing is shorter */
+ if (ec_iter->act_t == action)
+ goto add_free_ok;
+ goto add_free_exist;
+ } else {
+ /* add a new branch */
+ c_prev = c_iter;
+ ec_iter->nxt_t = c_iter->nxt_t;
+ s_iter->node_cnt +=
+ (s_new->node_cnt - 1);
+ goto add_free_match;
+ }
+ } else if (c_iter->nxt_f != NULL) {
+ if (ec_iter->nxt_f != NULL) {
+ /* jump to the next level */
+ c_prev = c_iter;
+ c_iter = c_iter->nxt_f;
+ ec_iter = ec_iter->nxt_f;
+ s_new->node_cnt--;
+ } else if (ec_iter->act_f_flg) {
+ /* existing is shorter */
+ if (ec_iter->act_f == action)
+ goto add_free_ok;
+ goto add_free_exist;
+ } else {
+ /* add a new branch */
+ c_prev = c_iter;
+ ec_iter->nxt_f = c_iter->nxt_f;
+ s_iter->node_cnt +=
+ (s_new->node_cnt - 1);
+ goto add_free_match;
+ }
+ } else
+ goto add_free_ok;
+ } else {
+ /* need to check other nodes on this level */
+ if (db_chain_lt(c_iter, ec_iter)) {
+ if (ec_iter->lvl_prv == NULL) {
+ /* add to the start of the level */
+ ec_iter->lvl_prv = c_iter;
+ c_iter->lvl_nxt = ec_iter;
+ if (ec_iter == s_iter->chains)
+ s_iter->chains = c_iter;
+ s_iter->node_cnt += s_new->node_cnt;
+ goto add_free_match;
+ } else
+ ec_iter = ec_iter->lvl_prv;
+ } else {
+ if (ec_iter->lvl_nxt == NULL) {
+ /* add to the end of the level */
+ ec_iter->lvl_nxt = c_iter;
+ c_iter->lvl_prv = ec_iter;
+ s_iter->node_cnt += s_new->node_cnt;
+ goto add_free_match;
+ } else if (db_chain_lt(c_iter,
+ ec_iter->lvl_nxt)) {
+ /* add new chain in between */
+ c_iter->lvl_nxt = ec_iter->lvl_nxt;
+ ec_iter->lvl_nxt->lvl_prv = c_iter;
+ ec_iter->lvl_nxt = c_iter;
+ c_iter->lvl_prv = ec_iter;
+ s_iter->node_cnt += s_new->node_cnt;
+ goto add_free_match;
+ } else
+ ec_iter = ec_iter->lvl_nxt;
+ }
+ }
+ } while ((c_iter != NULL) && (ec_iter != NULL));
+
+ /* we should never be here! */
+ return -EFAULT;
+
+add_free_exist:
+ rc = -EEXIST;
+ goto add_free;
+add_free_ok:
+ rc = 0;
+add_free:
+ /* free the new chain and its syscall struct */
+ _db_tree_free(s_new->chains);
+ free(s_new);
+ goto add_priority_update;
+add_free_match:
+ /* free the matching portion of new chain */
+ if (c_prev != NULL) {
+ c_prev->nxt_t = NULL;
+ c_prev->nxt_f = NULL;
+ _db_tree_free(s_new->chains);
+ }
+ free(s_new);
+ rc = 0;
+add_priority_update:
+ /* update the priority */
+ if (s_iter != NULL) {
+ s_iter->priority &= (~_DB_PRI_MASK_CHAIN);
+ s_iter->priority |= (_DB_PRI_MASK_CHAIN - s_iter->node_cnt);
+ }
+ return rc;
+}
--- /dev/null
+/**
+ * Enhanced Seccomp Filter DB
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _FILTER_DB_H
+#define _FILTER_DB_H
+
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+
+/* XXX - need to provide doxygen comments for the types here */
+
+struct db_api_arg {
+ unsigned int arg;
+ unsigned int op;
+ scmp_datum_t mask;
+ scmp_datum_t datum;
+
+ bool valid;
+};
+
+struct db_arg_chain_tree {
+ /* argument number (a0 = 0, a1 = 1, etc.) */
+ unsigned int arg;
+ /* argument bpf offset */
+ unsigned int arg_offset;
+
+ /* comparison operator */
+ enum scmp_compare op;
+ /* syscall argument value */
+ uint32_t mask;
+ uint32_t datum;
+
+ /* actions */
+ bool act_t_flg;
+ bool act_f_flg;
+ uint32_t act_t;
+ uint32_t act_f;
+
+ /* list of nodes on this level */
+ struct db_arg_chain_tree *lvl_prv, *lvl_nxt;
+
+ /* next node in the chain */
+ struct db_arg_chain_tree *nxt_t;
+ struct db_arg_chain_tree *nxt_f;
+
+ unsigned int refcnt;
+};
+#define ARG_MASK_MAX ((uint32_t)-1)
+#define db_chain_lt(x,y) \
+ (((x)->arg < (y)->arg) || \
+ (((x)->arg == (y)->arg) && \
+ (((x)->op < (y)->op) || (((x)->mask & (y)->mask) == (y)->mask))))
+#define db_chain_eq(x,y) \
+ (((x)->arg == (y)->arg) && \
+ ((x)->op == (y)->op) && ((x)->datum == (y)->datum) && \
+ ((x)->mask == (y)->mask))
+#define db_chain_gt(x,y) \
+ (((x)->arg > (y)->arg) || \
+ (((x)->arg == (y)->arg) && \
+ (((x)->op > (y)->op) || (((x)->mask & (y)->mask) != (y)->mask))))
+#define db_chain_action(x) \
+ (((x)->act_t_flg) || ((x)->act_f_flg))
+#define db_chain_zombie(x) \
+ ((x)->nxt_t == NULL && !((x)->act_t_flg) && \
+ (x)->nxt_f == NULL && !((x)->act_f_flg))
+#define db_chain_leaf(x) \
+ ((x)->nxt_t == NULL && (x)->nxt_f == NULL)
+#define db_chain_eq_result(x,y) \
+ ((((x)->nxt_t != NULL && (y)->nxt_t != NULL) || \
+ ((x)->nxt_t == NULL && (y)->nxt_t == NULL)) && \
+ (((x)->nxt_f != NULL && (y)->nxt_f != NULL) || \
+ ((x)->nxt_f == NULL && (y)->nxt_f == NULL)) && \
+ ((x)->act_t_flg == (y)->act_t_flg) && \
+ ((x)->act_f_flg == (y)->act_f_flg) && \
+ (((x)->act_t_flg && (x)->act_t == (y)->act_t) || \
+ (!((x)->act_t_flg))) && \
+ (((x)->act_f_flg && (x)->act_f == (y)->act_f) || \
+ (!((x)->act_f_flg))))
+
+struct db_sys_list {
+ /* native syscall number */
+ unsigned int num;
+
+ /* priority - higher is better */
+ unsigned int priority;
+
+ /* the argument chain heads */
+ struct db_arg_chain_tree *chains;
+ unsigned int node_cnt;
+
+ /* action in the case of no argument chains */
+ uint32_t action;
+
+ struct db_sys_list *next;
+ /* temporary use only by the BPF generator */
+ struct db_sys_list *pri_prv, *pri_nxt;
+
+ bool valid;
+};
+
+struct db_filter_attr {
+ /* action to take if we don't match an explicit allow/deny */
+ uint32_t act_default;
+ /* action to take if we don't match the architecture */
+ uint32_t act_badarch;
+ /* NO_NEW_PRIVS related attributes */
+ uint32_t nnp_enable;
+};
+
+struct db_filter {
+ /* target architecture */
+ const struct arch_def *arch;
+
+ /* syscall filters, kept as a sorted single-linked list */
+ struct db_sys_list *syscalls;
+};
+
+struct db_filter_col {
+ /* verification / state */
+ int state;
+
+ /* attributes */
+ struct db_filter_attr attr;
+
+ /* individual filters */
+ struct db_filter **filters;
+ unsigned int filter_cnt;
+};
+
+/**
+ * Iterate over each item in the DB list
+ * @param iter the iterator
+ * @param list the list
+ *
+ * This macro acts as for()/while() conditional and iterates the following
+ * statement for each item in the given list.
+ *
+ */
+#define db_list_foreach(iter,list) \
+ for (iter = (list); iter != NULL; iter = iter->next)
+
+int db_action_valid(uint32_t action);
+
+struct db_filter_col *db_col_init(uint32_t def_action);
+void db_col_reset(struct db_filter_col *col, uint32_t def_action);
+void db_col_release(struct db_filter_col *col);
+
+int db_col_valid(struct db_filter_col *col);
+
+int db_col_merge(struct db_filter_col *col_dst, struct db_filter_col *col_src);
+
+int db_col_arch_exist(struct db_filter_col *col, uint32_t arch_token);
+
+int db_col_attr_get(const struct db_filter_col *col,
+ enum scmp_filter_attr attr, uint32_t *value);
+int db_col_attr_set(struct db_filter_col *col,
+ enum scmp_filter_attr attr, uint32_t value);
+
+int db_col_db_add(struct db_filter_col *col, struct db_filter *db);
+int db_col_db_remove(struct db_filter_col *col, uint32_t arch_token);
+
+struct db_filter *db_init(const struct arch_def *arch);
+void db_reset(struct db_filter *db);
+void db_release(struct db_filter *db);
+
+int db_syscall_priority(struct db_filter *db,
+ unsigned int syscall, uint8_t priority);
+
+int db_rule_add(struct db_filter *db, uint32_t action, unsigned int syscall,
+ struct db_api_arg *chain);
+
+#endif
--- /dev/null
+/**
+ * Seccomp BPF Translator
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+#include "arch-x32.h"
+#include "gen_bpf.h"
+#include "db.h"
+#include "hash.h"
+#include "system.h"
+
+/* allocation increments */
+#define AINC_BLK 2
+#define AINC_PROG 64
+
+struct acc_state {
+ int32_t offset;
+ uint32_t mask;
+};
+
+enum bpf_jump_type {
+ TGT_NONE = 0,
+ TGT_K, /* immediate "k" value */
+ TGT_NXT, /* fall through to the next block */
+ TGT_IMM, /* resolved immediate value */
+ TGT_PTR_DB, /* pointer to part of the filter db */
+ TGT_PTR_BLK, /* pointer to an instruction block */
+ TGT_PTR_HSH, /* pointer to a block hash table */
+};
+
+struct bpf_jump {
+ union {
+ uint8_t imm_j;
+ uint32_t imm_k;
+ uint64_t hash;
+ struct db_arg_chain_tree *db;
+ struct bpf_blk *blk;
+ unsigned int nxt;
+ } tgt;
+ enum bpf_jump_type type;
+};
+#define _BPF_JMP_NO \
+ ((struct bpf_jump) { .type = TGT_NONE })
+#define _BPF_JMP_NXT(x) \
+ ((struct bpf_jump) { .type = TGT_NXT, .tgt = { .nxt = (x) } })
+#define _BPF_JMP_IMM(x) \
+ ((struct bpf_jump) { .type = TGT_IMM, .tgt = { .imm_j = (x) } })
+#define _BPF_JMP_DB(x) \
+ ((struct bpf_jump) { .type = TGT_PTR_DB, .tgt = { .db = (x) } })
+#define _BPF_JMP_BLK(x) \
+ ((struct bpf_jump) { .type = TGT_PTR_BLK, .tgt = { .blk = (x) } })
+#define _BPF_JMP_HSH(x) \
+ ((struct bpf_jump) { .type = TGT_PTR_HSH, .tgt = { .hash = (x) } })
+#define _BPF_K(x) \
+ ((struct bpf_jump) { .type = TGT_K, .tgt = { .imm_k = (x) } })
+#define _BPF_JMP_MAX 255
+#define _BPF_JMP_MAX_RET 255
+
+struct bpf_instr {
+ uint16_t op;
+ struct bpf_jump jt;
+ struct bpf_jump jf;
+ struct bpf_jump k;
+};
+#define _BPF_OFFSET_SYSCALL (offsetof(struct seccomp_data, nr))
+#define _BPF_SYSCALL _BPF_K(_BPF_OFFSET_SYSCALL)
+
+struct bpf_blk {
+ struct bpf_instr *blks;
+ unsigned int blk_cnt;
+ unsigned int blk_alloc;
+
+ /* priority - higher is better */
+ unsigned int priority;
+
+ /* status flags */
+ bool flag_hash; /* added to the hash table */
+ bool flag_dup; /* duplicate block and in use */
+ bool flag_unique; /* ->blks is unique to this block */
+
+ /* original db_arg_chain_tree node */
+ const struct db_arg_chain_tree *node;
+
+ /* used during block assembly */
+ uint64_t hash;
+ struct bpf_blk *hash_nxt;
+ struct bpf_blk *prev, *next;
+ struct bpf_blk *lvl_prv, *lvl_nxt;
+ struct acc_state acc_state;
+};
+#define _BLK_MSZE(x) \
+ ((x)->blk_cnt * sizeof(*((x)->blks)))
+
+struct bpf_hash_bkt {
+ struct bpf_blk *blk;
+ struct bpf_hash_bkt *next;
+ unsigned int found;
+};
+
+#define _BPF_HASH_BITS 8
+#define _BPF_HASH_SIZE (1 << _BPF_HASH_BITS)
+#define _BPF_HASH_MASK (_BPF_HASH_BITS - 1)
+struct bpf_state {
+ /* block hash table */
+ struct bpf_hash_bkt *htbl[_BPF_HASH_SIZE];
+
+ /* filter attributes */
+ const struct db_filter_attr *attr;
+ /* default action */
+ uint64_t def_hsh;
+
+ /* target arch - NOTE: be careful, temporary use only! */
+ const struct arch_def *arch;
+
+ /* bpf program */
+ struct bpf_program *bpf;
+};
+
+/**
+ * Populate a BPF instruction
+ * @param _ins the BPF instruction
+ * @param _op the BPF operand
+ * @param _jt the BPF jt value
+ * @param _jf the BPF jf value
+ * @param _k the BPF k value
+ *
+ * Set the given values on the provided bpf_instr struct.
+ *
+ */
+#define _BPF_INSTR(_ins,_op,_jt,_jf,_k) \
+ do { \
+ memset(&(_ins), 0, sizeof(_ins)); \
+ (_ins).op = (_op); \
+ (_ins).jt = _jt; \
+ (_ins).jf = _jf; \
+ (_ins).k = _k; \
+ } while (0)
+
+static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state,
+ const struct db_sys_list *sys,
+ const struct db_arg_chain_tree *chain,
+ const struct bpf_jump *nxt_jump,
+ struct acc_state *a_state);
+
+static struct bpf_blk *_hsh_remove(struct bpf_state *state, uint64_t h_val);
+static struct bpf_blk *_hsh_find(const struct bpf_state *state, uint64_t h_val);
+
+/**
+ * Free the BPF instruction block
+ * @param state the BPF state
+ * @param blk the BPF instruction block
+ *
+ * Free the BPF instruction block, any linked blocks are preserved and the hash
+ * table is not modified. In general, you probably want to use _blk_free()
+ * instead.
+ *
+ */
+static void __blk_free(struct bpf_state *state, struct bpf_blk *blk)
+{
+ struct bpf_blk *b_tmp;
+
+ while (blk->hash_nxt != NULL) {
+ b_tmp = blk->hash_nxt;
+ blk->hash_nxt = b_tmp->hash_nxt;
+ if (!b_tmp->flag_dup)
+ free(b_tmp);
+ }
+ if (blk->blks != NULL && blk->flag_unique)
+ free(blk->blks);
+ free(blk);
+}
+
+/**
+* Free the BPF instruction block
+ * @param state the BPF state
+ * @param blk the BPF instruction block
+ *
+ * Free the BPF instruction block including any linked blocks. The hash table
+ * is updated to reflect the newly removed block(s).
+ *
+ */
+static void _blk_free(struct bpf_state *state, struct bpf_blk *blk)
+{
+ int iter;
+ struct bpf_blk *b_iter;
+ struct bpf_instr *i_iter;
+
+ if (blk == NULL)
+ return;
+
+ /* remove this block from the hash table */
+ _hsh_remove(state, blk->hash);
+
+ /* run through the block freeing TGT_PTR_{BLK,HSH} jump targets */
+ for (iter = 0; iter < blk->blk_cnt; iter++) {
+ i_iter = &blk->blks[iter];
+ switch (i_iter->jt.type) {
+ case TGT_PTR_BLK:
+ _blk_free(state, i_iter->jt.tgt.blk);
+ break;
+ case TGT_PTR_HSH:
+ b_iter = _hsh_find(state, i_iter->jt.tgt.hash);
+ _blk_free(state, b_iter);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ switch (i_iter->jf.type) {
+ case TGT_PTR_BLK:
+ _blk_free(state, i_iter->jf.tgt.blk);
+ break;
+ case TGT_PTR_HSH:
+ b_iter = _hsh_find(state, i_iter->jf.tgt.hash);
+ _blk_free(state, b_iter);
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+ __blk_free(state, blk);
+}
+
+/**
+ * Append a new BPF instruction to an instruction block
+ * @param state the BPF state
+ * @param blk the existing instruction block, or NULL
+ * @param instr the new instruction
+ *
+ * Add the new BPF instruction to the end of the give instruction block. If
+ * the given instruction block is NULL, a new block will be allocated. Returns
+ * a pointer to the block on success, NULL on failure, and in the case of
+ * failure the instruction block is free'd.
+ *
+ */
+static struct bpf_blk *_blk_append(struct bpf_state *state,
+ struct bpf_blk *blk,
+ const struct bpf_instr *instr)
+{
+ struct bpf_instr *new;
+
+ if (blk == NULL) {
+ blk = malloc(sizeof(*blk));
+ if (blk == NULL)
+ return NULL;
+ memset(blk, 0, sizeof(*blk));
+ blk->flag_unique = true;
+ }
+ if ((blk->blk_cnt + 1) > blk->blk_alloc) {
+ blk->blk_alloc += AINC_BLK;
+ new = realloc(blk->blks, blk->blk_alloc * sizeof(*(blk->blks)));
+ if (new == NULL) {
+ _blk_free(state, blk);
+ return NULL;
+ }
+ blk->blks = new;
+ }
+ memcpy(&blk->blks[blk->blk_cnt++], instr, sizeof(*instr));
+
+ return blk;
+}
+
+/**
+ * Append a block of BPF instructions to the final BPF program
+ * @param prg the BPF program
+ * @param blk the BPF instruction block
+ *
+ * Add the BPF instruction block to the end of the BPF program and perform the
+ * necssary translation. Returns zero on success, negative values on failure
+ * and in the case of failure the BPF program is free'd.
+ *
+ */
+static int _bpf_append_blk(struct bpf_program *prg, const struct bpf_blk *blk)
+{
+ int rc;
+ bpf_instr_raw *i_new;
+ bpf_instr_raw *i_iter;
+ unsigned int old_cnt = prg->blk_cnt;
+ unsigned int iter;
+
+ /* (re)allocate the program memory */
+ prg->blk_cnt += blk->blk_cnt;
+ i_new = realloc(prg->blks, BPF_PGM_SIZE(prg));
+ if (i_new == NULL) {
+ rc = -ENOMEM;
+ goto bpf_append_blk_failure;
+ }
+ prg->blks = i_new;
+
+ /* transfer and translate the blocks to raw instructions */
+ for (iter = 0; iter < blk->blk_cnt; iter++) {
+ i_iter = &(prg->blks[old_cnt + iter]);
+
+ i_iter->code = blk->blks[iter].op;
+ switch (blk->blks[iter].jt.type) {
+ case TGT_NONE:
+ i_iter->jt = 0;
+ break;
+ case TGT_IMM:
+ /* jump to the value specified */
+ i_iter->jt = blk->blks[iter].jt.tgt.imm_j;
+ break;
+ default:
+ /* fatal error - we should never get here */
+ rc = -EFAULT;
+ goto bpf_append_blk_failure;
+ }
+ switch (blk->blks[iter].jf.type) {
+ case TGT_NONE:
+ i_iter->jf = 0;
+ break;
+ case TGT_IMM:
+ /* jump to the value specified */
+ i_iter->jf = blk->blks[iter].jf.tgt.imm_j;
+ break;
+ default:
+ /* fatal error - we should never get here */
+ rc = -EFAULT;
+ goto bpf_append_blk_failure;
+ }
+ switch (blk->blks[iter].k.type) {
+ case TGT_NONE:
+ i_iter->k = 0;
+ break;
+ case TGT_K:
+ i_iter->k = blk->blks[iter].k.tgt.imm_k;
+ break;
+ default:
+ /* fatal error - we should never get here */
+ rc = -EFAULT;
+ goto bpf_append_blk_failure;
+ }
+ }
+
+ return prg->blk_cnt;
+
+bpf_append_blk_failure:
+ prg->blk_cnt = 0;
+ free(prg->blks);
+ return rc;
+}
+
+/**
+ * Free the BPF program
+ * @param prg the BPF program
+ *
+ * Free the BPF program. None of the associated BPF state used to generate the
+ * BPF program is released in this function.
+ *
+ */
+static void _program_free(struct bpf_program *prg)
+{
+ if (prg == NULL)
+ return;
+
+ if (prg->blks != NULL)
+ free(prg->blks);
+ free(prg);
+}
+
+/**
+ * Free the BPF state
+ * @param the BPF state
+ *
+ * Free all of the BPF state, including the BPF program if present.
+ *
+ */
+static void _state_release(struct bpf_state *state)
+{
+ unsigned int bkt;
+ struct bpf_hash_bkt *iter;
+
+ if (state == NULL)
+ return;
+
+ /* release all of the hash table entries */
+ for (bkt = 0; bkt < _BPF_HASH_SIZE; bkt++) {
+ while (state->htbl[bkt]) {
+ iter = state->htbl[bkt];
+ state->htbl[bkt] = iter->next;
+ __blk_free(state, iter->blk);
+ free(iter);
+ }
+ }
+ _program_free(state->bpf);
+
+ memset(state, 0, sizeof(*state));
+}
+
+/**
+ * Add an instruction block to the BPF state hash table
+ * @param state the BPF state
+ * @param blk_p pointer to the BPF instruction block
+ * @param found initial found value (see _hsh_find_once() for description)
+ *
+ * This function adds an instruction block to the hash table, and frees the
+ * block if an identical instruction block already exists, returning a pointer
+ * to the original block in place of the given block. Returns zero on success
+ * and negative values on failure.
+ *
+ */
+static int _hsh_add(struct bpf_state *state, struct bpf_blk **blk_p,
+ unsigned int found)
+{
+ uint64_t h_val;
+ struct bpf_hash_bkt *h_new, *h_iter, *h_prev = NULL;
+ struct bpf_blk *blk = *blk_p;
+ struct bpf_blk *b_iter;
+
+ if (blk->flag_hash)
+ return 0;
+
+ h_new = malloc(sizeof(*h_new));
+ if (h_new == NULL)
+ return -ENOMEM;
+ memset(h_new, 0, sizeof(*h_new));
+
+ /* generate the hash */
+ h_val = jhash(blk->blks, _BLK_MSZE(blk), 0);
+ blk->hash = h_val;
+ blk->flag_hash = true;
+ blk->node = NULL;
+ h_new->blk = blk;
+ h_new->found = (found ? 1 : 0);
+
+ /* insert the block into the hash table */
+ h_iter = state->htbl[h_val & _BPF_HASH_MASK];
+ if (h_iter != NULL) {
+ do {
+ if ((h_iter->blk->hash == h_val) &&
+ (_BLK_MSZE(h_iter->blk) == _BLK_MSZE(blk)) &&
+ (memcmp(h_iter->blk->blks, blk->blks,
+ _BLK_MSZE(blk)) == 0)) {
+ /* duplicate block */
+ free(h_new);
+
+ /* store the duplicate block */
+ b_iter = h_iter->blk;
+ while (b_iter->hash_nxt != NULL)
+ b_iter = b_iter->hash_nxt;
+ b_iter->hash_nxt = blk;
+
+ /* in some cases we want to return the
+ * duplicate block */
+ if (found) {
+ blk->flag_dup = true;
+ return 0;
+ }
+
+ /* update the priority if needed */
+ if (h_iter->blk->priority < blk->priority)
+ h_iter->blk->priority = blk->priority;
+
+ /* try to save some memory */
+ free(blk->blks);
+ blk->blks = h_iter->blk->blks;
+ blk->flag_unique = false;
+
+ *blk_p = h_iter->blk;
+ return 0;
+ } else if (h_iter->blk->hash == h_val) {
+ /* hash collision */
+ if ((h_val >> 32) == 0xffffffff) {
+ /* overflow */
+ blk->flag_hash = false;
+ blk->hash = 0;
+ return -EFAULT;
+ }
+ h_val += ((uint64_t)1 << 32);
+ h_new->blk->hash = h_val;
+
+ /* restart at the beginning of the bucket */
+ h_iter = state->htbl[h_val & _BPF_HASH_MASK];
+ } else {
+ /* no match, move along */
+ h_prev = h_iter;
+ h_iter = h_iter->next;
+ }
+ } while (h_iter != NULL);
+ h_prev->next = h_new;
+ } else
+ state->htbl[h_val & _BPF_HASH_MASK] = h_new;
+
+ return 0;
+}
+
+/**
+ * Remove an entry from the hash table
+ * @param state the BPF state
+ * @param h_val the hash value
+ *
+ * Remove an entry from the hash table and return it to the caller, NULL is
+ * returned if the entry can not be found.
+ *
+ */
+static struct bpf_blk *_hsh_remove(struct bpf_state *state, uint64_t h_val)
+{
+ unsigned int bkt = h_val & _BPF_HASH_MASK;
+ struct bpf_blk *blk;
+ struct bpf_hash_bkt *h_iter, *h_prev = NULL;
+
+ h_iter = state->htbl[bkt];
+ while (h_iter != NULL) {
+ if (h_iter->blk->hash == h_val) {
+ if (h_prev != NULL)
+ h_prev->next = h_iter->next;
+ else
+ state->htbl[bkt] = h_iter->next;
+ blk = h_iter->blk;
+ free(h_iter);
+ return blk;
+ }
+ h_prev = h_iter;
+ h_iter = h_iter->next;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find and return a hash bucket
+ * @param state the BPF state
+ * @param h_val the hash value
+ *
+ * Find the entry associated with the given hash value and return it to the
+ * caller, NULL is returned if the entry can not be found. This function
+ * should not be called directly; use _hsh_find() and _hsh_find_once() instead.
+ *
+ */
+static struct bpf_hash_bkt *_hsh_find_bkt(const struct bpf_state *state,
+ uint64_t h_val)
+{
+ struct bpf_hash_bkt *h_iter;
+
+ h_iter = state->htbl[h_val & _BPF_HASH_MASK];
+ while (h_iter != NULL) {
+ if (h_iter->blk->hash == h_val)
+ return h_iter;
+ h_iter = h_iter->next;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find and only return an entry in the hash table once
+ * @param state the BPF state
+ * @param h_val the hash value
+ *
+ * Find the entry associated with the given hash value and return it to the
+ * caller if it has not be returned previously by this function; returns NULL
+ * if the entry can not be found or has already been returned in a previous
+ * call.
+ *
+ */
+static struct bpf_blk *_hsh_find_once(const struct bpf_state *state,
+ uint64_t h_val)
+{
+ struct bpf_hash_bkt *h_iter;
+
+ h_iter = _hsh_find_bkt(state, h_val);
+ if (h_iter == NULL || h_iter->found != 0)
+ return NULL;
+ h_iter->found = 1;
+ return h_iter->blk;
+}
+
+/**
+ * Finds an entry in the hash table
+ * @param state the BPF state
+ * @param h_val the hash value
+ *
+ * Find the entry associated with the given hash value and return it to the
+ * caller, NULL is returned if the entry can not be found.
+ *
+ */
+static struct bpf_blk *_hsh_find(const struct bpf_state *state, uint64_t h_val)
+{
+ struct bpf_hash_bkt *h_iter;
+
+ h_iter = _hsh_find_bkt(state, h_val);
+ if (h_iter == NULL)
+ return NULL;
+ return h_iter->blk;
+}
+
+/**
+ * Generate a BPF action instruction
+ * @param state the BPF state
+ * @param blk the BPF instruction block, or NULL
+ * @param action the desired action
+ *
+ * Generate a BPF action instruction and append it to the given instruction
+ * block. Returns a pointer to the instruction block on success, NULL on
+ * failure.
+ *
+ */
+static struct bpf_blk *_gen_bpf_action(struct bpf_state *state,
+ struct bpf_blk *blk, uint32_t action)
+{
+ struct bpf_instr instr;
+
+ _BPF_INSTR(instr, BPF_RET, _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(action));
+ return _blk_append(state, blk, &instr);
+}
+
+/**
+ * Generate a BPF action instruction and insert it into the hash table
+ * @param state the BPF state
+ * @param action the desired action
+ *
+ * Generate a BPF action instruction and insert it into the hash table.
+ * Returns a pointer to the instruction block on success, NULL on failure.
+ *
+ */
+static struct bpf_blk *_gen_bpf_action_hsh(struct bpf_state *state,
+ uint32_t action)
+{
+ struct bpf_blk *blk;
+
+ blk = _gen_bpf_action(state, NULL, action);
+ if (blk == NULL)
+ return NULL;
+ if (_hsh_add(state, &blk, 0) < 0) {
+ _blk_free(state, blk);
+ return NULL;
+ }
+
+ return blk;
+}
+
+/**
+ * Generate a BPF instruction block for a given chain node
+ * @param state the BPF state
+ * @param node the filter chain node
+ * @param a_state the accumulator state
+ *
+ * Generate BPF instructions to execute the filter for the given chain node.
+ * Returns a pointer to the instruction block on success, NULL on failure.
+ *
+ */
+static struct bpf_blk *_gen_bpf_node(struct bpf_state *state,
+ const struct db_arg_chain_tree *node,
+ struct acc_state *a_state)
+{
+ int32_t acc_offset;
+ uint32_t acc_mask;
+ uint64_t act_t_hash = 0, act_f_hash = 0;
+ struct bpf_blk *blk = NULL, *b_act;
+ struct bpf_instr instr;
+ struct acc_state a_state_orig = *a_state;
+
+ /* generate the action blocks */
+ if (node->act_t_flg) {
+ b_act = _gen_bpf_action_hsh(state, node->act_t);
+ if (b_act == NULL)
+ goto node_failure;
+ act_t_hash = b_act->hash;
+ }
+ if (node->act_f_flg) {
+ b_act = _gen_bpf_action_hsh(state, node->act_f);
+ if (b_act == NULL)
+ goto node_failure;
+ act_f_hash = b_act->hash;
+ }
+
+ /* check the accumulator state */
+ acc_offset = node->arg_offset;
+ acc_mask = node->mask;
+ if (acc_offset < 0)
+ goto node_failure;
+ if ((acc_offset != a_state->offset) ||
+ ((acc_mask & a_state->mask) != acc_mask)) {
+ /* reload the accumulator */
+ a_state->offset = acc_offset;
+ a_state->mask = ARG_MASK_MAX;
+ _BPF_INSTR(instr, BPF_LD + BPF_ABS,
+ _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(acc_offset));
+ blk = _blk_append(state, blk, &instr);
+ if (blk == NULL)
+ goto node_failure;
+ }
+ if (acc_mask != a_state->mask) {
+ /* apply the bitmask */
+ a_state->mask = acc_mask;
+ _BPF_INSTR(instr, BPF_ALU + BPF_AND,
+ _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(acc_mask));
+ blk = _blk_append(state, blk, &instr);
+ if (blk == NULL)
+ goto node_failure;
+ }
+
+ /* check the accumulator against the datum */
+ switch (node->op) {
+ case SCMP_CMP_MASKED_EQ:
+ case SCMP_CMP_EQ:
+ _BPF_INSTR(instr, BPF_JMP + BPF_JEQ,
+ _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(node->datum));
+ break;
+ case SCMP_CMP_GT:
+ _BPF_INSTR(instr, BPF_JMP + BPF_JGT,
+ _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(node->datum));
+ break;
+ case SCMP_CMP_GE:
+ _BPF_INSTR(instr, BPF_JMP + BPF_JGE,
+ _BPF_JMP_NO, _BPF_JMP_NO, _BPF_K(node->datum));
+ break;
+ case SCMP_CMP_NE:
+ case SCMP_CMP_LT:
+ case SCMP_CMP_LE:
+ /* if we hit here it means the filter db isn't correct */
+ default:
+ /* fatal error, we should never get here */
+ goto node_failure;
+ }
+
+ /* fixup the jump targets */
+ if (node->nxt_t != NULL)
+ instr.jt = _BPF_JMP_DB(node->nxt_t);
+ else if (node->act_t_flg)
+ instr.jt = _BPF_JMP_HSH(act_t_hash);
+ else
+ instr.jt = _BPF_JMP_NXT(0);
+ if (node->nxt_f != NULL)
+ instr.jf = _BPF_JMP_DB(node->nxt_f);
+ else if (node->act_f_flg)
+ instr.jf = _BPF_JMP_HSH(act_f_hash);
+ else
+ instr.jf = _BPF_JMP_NXT(0);
+ blk = _blk_append(state, blk, &instr);
+ if (blk == NULL)
+ goto node_failure;
+
+ blk->node = node;
+ blk->acc_state = a_state_orig;
+ return blk;
+
+node_failure:
+ _blk_free(state, blk);
+ return NULL;
+}
+
+/**
+ * Resolve the jump targets in a BPF instruction block
+ * @param state the BPF state
+ * @param sys the syscall filter
+ * @param blk the BPF instruction block
+ * @param nxt_jump the jump to fallthrough to at the end of the level
+ *
+ * Resolve the jump targets in a BPF instruction block generated by the
+ * _gen_bpf_chain_lvl() function and adds the resulting block to the hash
+ * table. Returns a pointer to the new instruction block on success, NULL on
+ * failure.
+ *
+ */
+static struct bpf_blk *_gen_bpf_chain_lvl_res(struct bpf_state *state,
+ const struct db_sys_list *sys,
+ struct bpf_blk *blk,
+ const struct bpf_jump *nxt_jump)
+{
+ int rc;
+ unsigned int iter;
+ struct bpf_blk *b_new;
+ struct bpf_instr *i_iter;
+ struct db_arg_chain_tree *node;
+
+ if (blk->flag_hash)
+ return blk;
+
+ /* convert TGT_PTR_DB to TGT_PTR_HSH references */
+ for (iter = 0; iter < blk->blk_cnt; iter++) {
+ i_iter = &blk->blks[iter];
+ switch (i_iter->jt.type) {
+ case TGT_NONE:
+ case TGT_IMM:
+ case TGT_PTR_HSH:
+ /* ignore these jump types */
+ break;
+ case TGT_PTR_BLK:
+ b_new = _gen_bpf_chain_lvl_res(state, sys,
+ i_iter->jt.tgt.blk,
+ nxt_jump);
+ if (b_new == NULL)
+ return NULL;
+ i_iter->jt = _BPF_JMP_HSH(b_new->hash);
+ break;
+ case TGT_PTR_DB:
+ node = (struct db_arg_chain_tree *)i_iter->jt.tgt.db;
+ b_new = _gen_bpf_chain(state, sys, node,
+ nxt_jump, &blk->acc_state);
+ if (b_new == NULL)
+ return NULL;
+ i_iter->jt = _BPF_JMP_HSH(b_new->hash);
+ break;
+ default:
+ /* we should not be here */
+ return NULL;
+ }
+ switch (i_iter->jf.type) {
+ case TGT_NONE:
+ case TGT_IMM:
+ case TGT_PTR_HSH:
+ /* ignore these jump types */
+ break;
+ case TGT_PTR_BLK:
+ b_new = _gen_bpf_chain_lvl_res(state, sys,
+ i_iter->jf.tgt.blk,
+ nxt_jump);
+ if (b_new == NULL)
+ return NULL;
+ i_iter->jf = _BPF_JMP_HSH(b_new->hash);
+ break;
+ case TGT_PTR_DB:
+ node = (struct db_arg_chain_tree *)i_iter->jf.tgt.db;
+ b_new = _gen_bpf_chain(state, sys, node,
+ nxt_jump, &blk->acc_state);
+ if (b_new == NULL)
+ return NULL;
+ i_iter->jf = _BPF_JMP_HSH(b_new->hash);
+ break;
+ default:
+ /* we should not be here */
+ return NULL;
+ }
+ switch (i_iter->k.type) {
+ case TGT_NONE:
+ case TGT_K:
+ case TGT_PTR_HSH:
+ /* ignore these jump types */
+ break;
+ default:
+ /* we should not be here */
+ return NULL;
+ }
+ }
+
+ /* insert the block into the hash table */
+ rc = _hsh_add(state, &blk, 0);
+ if (rc < 0)
+ return NULL;
+
+ return blk;
+}
+
+/**
+ * Generates the BPF instruction blocks for a given filter chain
+ * @param state the BPF state
+ * @param sys the syscall filter
+ * @param chain the filter chain
+ * @param nxt_jump the jump to fallthrough to at the end of the level
+ * @param a_state the accumulator state
+ *
+ * Generate the BPF instruction blocks for the given filter chain and return
+ * a pointer to the first block on success; returns NULL on failure.
+ *
+ */
+static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state,
+ const struct db_sys_list *sys,
+ const struct db_arg_chain_tree *chain,
+ const struct bpf_jump *nxt_jump,
+ struct acc_state *a_state)
+{
+ struct bpf_blk *b_head = NULL, *b_tail = NULL;
+ struct bpf_blk *b_prev, *b_next, *b_iter;
+ struct bpf_instr *i_iter;
+ const struct db_arg_chain_tree *c_iter;
+ unsigned int iter;
+ struct bpf_jump nxt_jump_tmp;
+
+ if (chain == NULL) {
+ b_head = _gen_bpf_action(state, NULL, sys->action);
+ if (b_head == NULL)
+ goto chain_failure;
+ b_tail = b_head;
+ } else {
+ /* find the starting node of the level */
+ c_iter = chain;
+ while (c_iter->lvl_prv != NULL)
+ c_iter = c_iter->lvl_prv;
+
+ /* build all of the blocks for this level */
+ do {
+ b_iter = _gen_bpf_node(state, c_iter, a_state);
+ if (b_iter == NULL)
+ goto chain_failure;
+ if (b_head != NULL) {
+ b_iter->lvl_prv = b_tail;
+ b_tail->lvl_nxt = b_iter;
+ b_tail = b_iter;
+ } else {
+ b_head = b_iter;
+ b_tail = b_iter;
+ }
+ c_iter = c_iter->lvl_nxt;
+ } while (c_iter != NULL);
+
+ /* resolve the TGT_NXT jumps */
+ b_iter = b_head;
+ do {
+ b_next = b_iter->lvl_nxt;
+ for (iter = 0; iter < b_iter->blk_cnt; iter++) {
+ i_iter = &b_iter->blks[iter];
+ if (i_iter->jt.type == TGT_NXT) {
+ if (i_iter->jt.tgt.nxt != 0)
+ goto chain_failure;
+ if (b_next == NULL)
+ i_iter->jt = *nxt_jump;
+ else
+ i_iter->jt =
+ _BPF_JMP_BLK(b_next);
+ }
+ if (i_iter->jf.type == TGT_NXT) {
+ if (i_iter->jf.tgt.nxt != 0)
+ goto chain_failure;
+ if (b_next == NULL)
+ i_iter->jf = *nxt_jump;
+ else
+ i_iter->jf =
+ _BPF_JMP_BLK(b_next);
+ }
+ }
+ b_iter = b_next;
+ } while (b_iter != NULL);
+ }
+
+ /* resolve all of the blocks */
+ memset(&nxt_jump_tmp, 0, sizeof(nxt_jump_tmp));
+ b_iter = b_tail;
+ do {
+ /* b_iter may change after resolving, so save the linkage */
+ b_prev = b_iter->lvl_prv;
+ b_next = b_iter->lvl_nxt;
+
+ nxt_jump_tmp = _BPF_JMP_BLK(b_next);
+ b_iter = _gen_bpf_chain_lvl_res(state, sys, b_iter,
+ (b_next == NULL ?
+ nxt_jump :
+ &nxt_jump_tmp));
+ if (b_iter == NULL)
+ goto chain_failure;
+
+ /* restore the block linkage on this level */
+ if (b_prev != NULL)
+ b_prev->lvl_nxt = b_iter;
+ b_iter->lvl_prv = b_prev;
+ b_iter->lvl_nxt = b_next;
+ if (b_next != NULL)
+ b_next->lvl_prv = b_iter;
+ if (b_iter->lvl_prv == NULL)
+ b_head = b_iter;
+
+ b_iter = b_prev;
+ } while (b_iter != NULL);
+
+ return b_head;
+
+chain_failure:
+ while (b_head != NULL) {
+ b_iter = b_head;
+ b_head = b_iter->lvl_nxt;
+ _blk_free(state, b_iter);
+ }
+ return NULL;
+}
+
+/**
+ * Generate the BPF instruction blocks for a given syscall
+ * @param state the BPF state
+ * @param sys the syscall filter DB entry
+ * @param nxt_hash the hash value of the next syscall filter DB entry
+ * @param acc_reset accumulator reset flag
+ *
+ * Generate the BPF instruction blocks for the given syscall filter and return
+ * a pointer to the first block on success; returns NULL on failure. It is
+ * important to note that the block returned has not been added to the hash
+ * table, however, any linked/referenced blocks have been added to the hash
+ * table.
+ *
+ */
+static struct bpf_blk *_gen_bpf_syscall(struct bpf_state *state,
+ const struct db_sys_list *sys,
+ uint64_t nxt_hash,
+ bool acc_reset)
+{
+ int rc;
+ struct bpf_instr instr;
+ struct bpf_blk *blk_c, *blk_s = NULL;
+ struct bpf_jump def_jump;
+ struct acc_state a_state;
+
+ /* we do the memset before the assignment to keep valgrind happy */
+ memset(&def_jump, 0, sizeof(def_jump));
+ def_jump = _BPF_JMP_HSH(state->def_hsh);
+
+ /* setup the accumulator state */
+ if (acc_reset) {
+ _BPF_INSTR(instr, BPF_LD + BPF_ABS, _BPF_JMP_NO, _BPF_JMP_NO,
+ _BPF_SYSCALL);
+ blk_s = _blk_append(state, NULL, &instr);
+ if (blk_s == NULL)
+ return NULL;
+ a_state.offset = _BPF_OFFSET_SYSCALL;
+ a_state.mask = ARG_MASK_MAX;
+ } else {
+ /* set the accumulator state to an unknown value */
+ a_state.offset = -1;
+ a_state.mask = ARG_MASK_MAX;
+ }
+
+ /* generate the argument chains */
+ blk_c = _gen_bpf_chain(state, sys, sys->chains, &def_jump, &a_state);
+ if (blk_c == NULL)
+ return NULL;
+
+ /* syscall check */
+ _BPF_INSTR(instr, BPF_JMP + BPF_JEQ,
+ _BPF_JMP_HSH(blk_c->hash), _BPF_JMP_HSH(nxt_hash),
+ _BPF_K(sys->num));
+ blk_s = _blk_append(state, blk_s, &instr);
+ if (blk_s == NULL)
+ return NULL;
+ blk_s->priority = sys->priority;
+
+ /* add to the hash table */
+ rc = _hsh_add(state, &blk_s, 1);
+ if (rc < 0) {
+ _blk_free(state, blk_s);
+ return NULL;
+ }
+
+ return blk_s;
+}
+
+/**
+ * Generate the BPF instruction blocks for a given filter/architecture
+ * @param state the BPF state
+ * @param db the filter DB
+ * @param db_secondary the secondary DB
+ *
+ * Generate the BPF instruction block for the given filter DB(s)/architecture(s)
+ * and return a pointer to the block on succes, NULL on failure. The resulting
+ * block assumes that the architecture token has already been loaded into the
+ * BPF accumulator.
+ *
+ */
+static struct bpf_blk *_gen_bpf_arch(struct bpf_state *state,
+ const struct db_filter *db,
+ const struct db_filter *db_secondary)
+{
+ int rc;
+ unsigned int blk_cnt = 0;
+ bool acc_reset;
+ struct bpf_instr instr;
+ struct db_sys_list *s_head = NULL, *s_tail = NULL, *s_iter, *s_iter_b;
+ struct bpf_blk *b_head = NULL, *b_tail = NULL, *b_iter, *b_new;
+
+ state->arch = db->arch;
+
+ /* sort the syscall list */
+ db_list_foreach(s_iter, db->syscalls) {
+ if (s_head != NULL) {
+ s_iter_b = s_head;
+ while ((s_iter_b->pri_nxt != NULL) &&
+ (s_iter->priority <= s_iter_b->priority))
+ s_iter_b = s_iter_b->pri_nxt;
+
+ if (s_iter->priority > s_iter_b->priority) {
+ s_iter->pri_prv = s_iter_b->pri_prv;
+ s_iter->pri_nxt = s_iter_b;
+ if (s_iter_b == s_head) {
+ s_head->pri_prv = s_iter;
+ s_head = s_iter;
+ } else {
+ s_iter->pri_prv->pri_nxt = s_iter;
+ s_iter->pri_nxt->pri_prv = s_iter;
+ }
+ } else {
+ s_iter->pri_prv = s_tail;
+ s_iter->pri_nxt = NULL;
+ s_iter->pri_prv->pri_nxt = s_iter;
+ s_tail = s_iter;
+ }
+ } else {
+ s_head = s_iter;
+ s_tail = s_iter;
+ s_head->pri_prv = NULL;
+ s_head->pri_nxt = NULL;
+ }
+ }
+ if (db_secondary != NULL) {
+ db_list_foreach(s_iter, db_secondary->syscalls) {
+ if (s_head != NULL) {
+ s_iter_b = s_head;
+ while ((s_iter_b->pri_nxt != NULL) &&
+ (s_iter->priority <= s_iter_b->priority))
+ s_iter_b = s_iter_b->pri_nxt;
+
+ if (s_iter->priority > s_iter_b->priority) {
+ s_iter->pri_prv = s_iter_b->pri_prv;
+ s_iter->pri_nxt = s_iter_b;
+ if (s_iter_b == s_head) {
+ s_head->pri_prv = s_iter;
+ s_head = s_iter;
+ } else {
+ s_iter->pri_prv->pri_nxt =
+ s_iter;
+ s_iter->pri_nxt->pri_prv =
+ s_iter;
+ }
+ } else {
+ s_iter->pri_prv = s_tail;
+ s_iter->pri_nxt = NULL;
+ s_iter->pri_prv->pri_nxt = s_iter;
+ s_tail = s_iter;
+ }
+ } else {
+ s_head = s_iter;
+ s_tail = s_iter;
+ s_head->pri_prv = NULL;
+ s_head->pri_nxt = NULL;
+ }
+ }
+ }
+
+ if ((db->arch->token == SCMP_ARCH_X86_64 ||
+ db->arch->token == SCMP_ARCH_X32) && (db_secondary == NULL))
+ acc_reset = false;
+ else
+ acc_reset = true;
+
+ /* create the syscall filters and add them to block list group */
+ for (s_iter = s_tail; s_iter != NULL; s_iter = s_iter->pri_prv) {
+ if (!s_iter->valid)
+ continue;
+
+ /* build the syscall filter */
+ b_new = _gen_bpf_syscall(state, s_iter,
+ (b_head == NULL ?
+ state->def_hsh : b_head->hash),
+ (s_iter == s_head ?
+ acc_reset : false));
+ if (b_new == NULL)
+ goto arch_failure;
+
+ /* add the filter to the list head */
+ b_new->prev = NULL;
+ b_new->next = b_head;
+ if (b_tail != NULL) {
+ b_head->prev = b_new;
+ b_head = b_new;
+ } else {
+ b_head = b_new;
+ b_tail = b_head;
+ }
+
+ if (b_tail->next != NULL)
+ b_tail = b_tail->next;
+ blk_cnt++;
+ }
+
+ /* additional ABI filtering */
+ if ((db->arch->token == SCMP_ARCH_X86_64 ||
+ db->arch->token == SCMP_ARCH_X32) && (db_secondary == NULL)) {
+ _BPF_INSTR(instr, BPF_LD + BPF_ABS, _BPF_JMP_NO, _BPF_JMP_NO,
+ _BPF_SYSCALL);
+ b_new = _blk_append(state, NULL, &instr);
+ if (b_new == NULL)
+ goto arch_failure;
+ if (db->arch->token == SCMP_ARCH_X86_64) {
+ /* filter out x32 */
+ _BPF_INSTR(instr, BPF_JMP + BPF_JGE,
+ _BPF_JMP_NXT(blk_cnt++), _BPF_JMP_NO,
+ _BPF_K(X32_SYSCALL_BIT));
+ if (b_head != NULL)
+ instr.jf = _BPF_JMP_HSH(b_head->hash);
+ else
+ instr.jf = _BPF_JMP_HSH(state->def_hsh);
+ } else if (db->arch->token == SCMP_ARCH_X32) {
+ /* filter out x86_64 */
+ _BPF_INSTR(instr, BPF_JMP + BPF_JGE,
+ _BPF_JMP_NO, _BPF_JMP_NXT(blk_cnt++),
+ _BPF_K(X32_SYSCALL_BIT));
+ if (b_head != NULL)
+ instr.jt = _BPF_JMP_HSH(b_head->hash);
+ else
+ instr.jt = _BPF_JMP_HSH(state->def_hsh);
+ } else
+ /* we should never get here */
+ goto arch_failure;
+ b_new = _blk_append(state, b_new, &instr);
+ if (b_new == NULL)
+ goto arch_failure;
+ b_new->next = b_head;
+ if (b_head != NULL)
+ b_head->prev = b_new;
+ b_head = b_new;
+ rc = _hsh_add(state, &b_head, 1);
+ if (rc < 0)
+ goto arch_failure;
+ }
+
+ /* do the ABI/architecture check */
+ _BPF_INSTR(instr, BPF_JMP + BPF_JEQ,
+ _BPF_JMP_NO, _BPF_JMP_NXT(blk_cnt++),
+ _BPF_K(db->arch->token_bpf));
+ if (b_head != NULL)
+ instr.jt = _BPF_JMP_HSH(b_head->hash);
+ else
+ instr.jt = _BPF_JMP_HSH(state->def_hsh);
+ b_new = _blk_append(state, NULL, &instr);
+ if (b_new == NULL)
+ goto arch_failure;
+ b_new->next = b_head;
+ if (b_head != NULL)
+ b_head->prev = b_new;
+ b_head = b_new;
+ rc = _hsh_add(state, &b_head, 1);
+ if (rc < 0)
+ goto arch_failure;
+
+ state->arch = NULL;
+ return b_head;
+
+arch_failure:
+ /* NOTE: we do the cleanup here and not just return an error as all of
+ * the instruction blocks may not be added to the hash table when we
+ * hit an error */
+ state->arch = NULL;
+ b_iter = b_head;
+ while (b_iter != NULL) {
+ b_new = b_iter->next;
+ _blk_free(state, b_iter);
+ b_iter = b_new;
+ }
+ return NULL;
+}
+
+/**
+ * Find the target block for the "next" jump
+ * @param blk the instruction block
+ * @param nxt the next offset
+ *
+ * Find the target block for the TGT_NXT jump using the given offset. Returns
+ * a pointer to the target block on success or NULL on failure.
+ *
+ */
+static struct bpf_blk *_gen_bpf_find_nxt(const struct bpf_blk *blk,
+ unsigned int nxt)
+{
+ struct bpf_blk *iter = blk->next;
+
+ for (; (iter != NULL) && (nxt > 0); nxt--)
+ iter = iter->next;
+
+ return iter;
+}
+
+/**
+ * Manage jumps to return instructions
+ * @param state the BPF state
+ * @param blk the instruction block to check
+ * @param offset the instruction offset into the instruction block
+ * @param blk_ret the return instruction block
+ *
+ * Using the given block and instruction offset, calculate the jump distance
+ * between the jumping instruction and return instruction block. If the jump
+ * distance is too great, duplicate the return instruction to reduce the
+ * distance to the maximum value. Returns 1 if a long jump was added, zero if
+ * the existing jump is valid, and negative values on failure.
+ *
+ */
+static int _gen_bpf_build_jmp_ret(struct bpf_state *state,
+ struct bpf_blk *blk, unsigned int offset,
+ struct bpf_blk *blk_ret)
+{
+ unsigned int j_len;
+ uint64_t tgt_hash = blk_ret->hash;
+ struct bpf_blk *b_jmp, *b_new;
+
+ /* calculate the jump distance */
+ j_len = blk->blk_cnt - (offset + 1);
+ b_jmp = blk->next;
+ while (b_jmp != NULL && b_jmp != blk_ret && j_len < _BPF_JMP_MAX_RET) {
+ j_len += b_jmp->blk_cnt;
+ b_jmp = b_jmp->next;
+ }
+ if (j_len <= _BPF_JMP_MAX_RET && b_jmp == blk_ret)
+ return 0;
+ if (b_jmp == NULL)
+ return -EFAULT;
+
+ /* we need a closer return instruction, see if one already exists */
+ j_len = blk->blk_cnt - (offset + 1);
+ b_jmp = blk->next;
+ while (b_jmp != NULL && b_jmp->hash != tgt_hash &&
+ j_len < _BPF_JMP_MAX_RET) {
+ j_len += b_jmp->blk_cnt;
+ b_jmp = b_jmp->next;
+ }
+ if (j_len <= _BPF_JMP_MAX_RET && b_jmp->hash == tgt_hash)
+ return 0;
+ if (b_jmp == NULL)
+ return -EFAULT;
+
+ /* we need to insert a new return instruction - create one */
+ b_new = _gen_bpf_action(state, NULL, blk_ret->blks[0].k.tgt.imm_k);
+ if (b_new == NULL)
+ return -EFAULT;
+
+ /* NOTE - we need to be careful here, we're giving the block a hash
+ * value (this is a sneaky way to ensure we leverage the
+ * inserted long jumps as much as possible) but we never add the
+ * block to the hash table so it won't get cleaned up
+ * automatically */
+ b_new->hash = tgt_hash;
+
+ /* insert the jump after the current jumping block */
+ b_new->prev = blk;
+ b_new->next = blk->next;
+ blk->next->prev = b_new;
+ blk->next = b_new;
+
+ return 1;
+}
+
+/**
+ * Manage jump lengths by duplicating and adding jumps if needed
+ * @param state the BPF state
+ * @param tail the tail of the instruction block list
+ * @param blk the instruction block to check
+ * @param offset the instruction offset into the instruction block
+ * @param tgt_hash the hash of the jump destination block
+ *
+ * Using the given block and instruction offset, calculate the jump distance
+ * between the jumping instruction and the destination. If the jump distance
+ * is too great, add a long jump instruction to reduce the distance to a legal
+ * value. Returns 1 if a new instruction was added, zero if the existing jump
+ * is valid, and negative values on failure.
+ *
+ */
+static int _gen_bpf_build_jmp(struct bpf_state *state,
+ struct bpf_blk *tail,
+ struct bpf_blk *blk, unsigned int offset,
+ uint64_t tgt_hash)
+{
+ int rc;
+ unsigned int jmp_len;
+ struct bpf_instr instr;
+ struct bpf_blk *b_new, *b_jmp, *b_tgt;
+
+ /* find the jump target */
+ b_tgt = tail;
+ while (b_tgt != blk && b_tgt->hash != tgt_hash)
+ b_tgt = b_tgt->prev;
+ if (b_tgt == blk)
+ return -EFAULT;
+
+ if (b_tgt->blk_cnt == 1 && b_tgt->blks[0].op == BPF_RET) {
+ rc = _gen_bpf_build_jmp_ret(state, blk, offset, b_tgt);
+ if (rc == 1)
+ return 1;
+ else if (rc < 0)
+ return rc;
+ }
+
+ /* calculate the jump distance */
+ jmp_len = blk->blk_cnt - (offset + 1);
+ b_jmp = blk->next;
+ while (b_jmp != NULL && b_jmp != b_tgt && jmp_len < _BPF_JMP_MAX) {
+ jmp_len += b_jmp->blk_cnt;
+ b_jmp = b_jmp->next;
+ }
+ if (jmp_len <= _BPF_JMP_MAX && b_jmp == b_tgt)
+ return 0;
+ if (b_jmp == NULL)
+ return -EFAULT;
+
+ /* we need a long jump, see if one already exists */
+ jmp_len = blk->blk_cnt - (offset + 1);
+ b_jmp = blk->next;
+ while (b_jmp != NULL && b_jmp->hash != tgt_hash &&
+ jmp_len < _BPF_JMP_MAX) {
+ jmp_len += b_jmp->blk_cnt;
+ b_jmp = b_jmp->next;
+ }
+ if (jmp_len <= _BPF_JMP_MAX && b_jmp->hash == tgt_hash)
+ return 0;
+ if (b_jmp == NULL)
+ return -EFAULT;
+
+ /* we need to insert a long jump - create one */
+ _BPF_INSTR(instr, BPF_JMP + BPF_JA,
+ _BPF_JMP_NO, _BPF_JMP_NO, _BPF_JMP_HSH(tgt_hash));
+ b_new = _blk_append(state, NULL, &instr);
+ if (b_new == NULL)
+ return -EFAULT;
+
+ /* NOTE - we need to be careful here, we're giving the block a hash
+ * value (this is a sneaky way to ensure we leverage the
+ * inserted long jumps as much as possible) but we never add the
+ * block to the hash table so it won't get cleaned up
+ * automatically */
+ b_new->hash = tgt_hash;
+
+ /* insert the jump after the current jumping block */
+ b_new->prev = blk;
+ b_new->next = blk->next;
+ blk->next->prev = b_new;
+ blk->next = b_new;
+
+ return 1;
+}
+
+/**
+ * Generate the BPF program for the given filter collection
+ * @param state the BPF state
+ * @param col the filter collection
+ *
+ * Generate the BPF program for the given filter collection. Returns zero on
+ * success, negative values on failure.
+ *
+ */
+static int _gen_bpf_build_bpf(struct bpf_state *state,
+ const struct db_filter_col *col)
+{
+ int rc;
+ int iter;
+ uint64_t h_val;
+ unsigned int res_cnt;
+ unsigned int jmp_len;
+ int arch_x86_64 = -1, arch_x32 = -1;
+ struct bpf_instr instr;
+ struct bpf_instr *i_iter;
+ struct bpf_blk *b_badarch, *b_default;
+ struct bpf_blk *b_head = NULL, *b_tail = NULL, *b_iter, *b_new, *b_jmp;
+ struct db_filter *db_secondary = NULL;
+
+ if (col->filter_cnt == 0)
+ return -EINVAL;
+
+ /* generate the badarch action */
+ b_badarch = _gen_bpf_action(state, NULL, state->attr->act_badarch);
+ if (b_badarch == NULL)
+ return -ENOMEM;
+ rc = _hsh_add(state, &b_badarch, 1);
+ if (rc < 0)
+ return rc;
+
+ /* generate the default action */
+ b_default = _gen_bpf_action(state, NULL, state->attr->act_default);
+ if (b_default == NULL)
+ return -ENOMEM;
+ rc = _hsh_add(state, &b_default, 0);
+ if (rc < 0)
+ return rc;
+ state->def_hsh = b_default->hash;
+
+ /* load the architecture token/number */
+ _BPF_INSTR(instr, BPF_LD + BPF_ABS, _BPF_JMP_NO, _BPF_JMP_NO,
+ _BPF_K(offsetof(struct seccomp_data, arch)));
+ b_head = _blk_append(state, NULL, &instr);
+ if (b_head == NULL)
+ return -ENOMEM;
+ rc = _hsh_add(state, &b_head, 1);
+ if (rc < 0)
+ return rc;
+ b_tail = b_head;
+
+ /* generate the per-architecture filters */
+ for (iter = 0; iter < col->filter_cnt; iter++) {
+ if (col->filters[iter]->arch->token == SCMP_ARCH_X86_64)
+ arch_x86_64 = iter;
+ if (col->filters[iter]->arch->token == SCMP_ARCH_X32)
+ arch_x32 = iter;
+ }
+ for (iter = 0; iter < col->filter_cnt; iter++) {
+ /* figure out the secondary arch filter mess */
+ if (iter == arch_x86_64) {
+ if (arch_x32 > iter)
+ db_secondary = col->filters[arch_x32];
+ else if (arch_x32 >= 0)
+ continue;
+ } else if (iter == arch_x32) {
+ if (arch_x86_64 > iter)
+ db_secondary = col->filters[arch_x86_64];
+ else if (arch_x86_64 >= 0)
+ continue;
+ } else
+ db_secondary = NULL;
+
+ /* create the filter for the architecture(s) */
+ b_new = _gen_bpf_arch(state, col->filters[iter], db_secondary);
+ if (b_new == NULL)
+ return -ENOMEM;
+ b_new->prev = b_tail;
+ b_tail->next = b_new;
+ b_tail = b_new;
+ while (b_tail->next != NULL)
+ b_tail = b_tail->next;
+ }
+
+ /* add a badarch action to the end */
+ b_badarch->prev = b_tail;
+ b_badarch->next = NULL;
+ b_tail->next = b_badarch;
+ b_tail = b_badarch;
+
+ /* resolve any TGT_NXT jumps at the top level */
+ b_iter = b_head;
+ do {
+ for (iter = 0; iter < b_iter->blk_cnt; iter++) {
+ i_iter = &b_iter->blks[iter];
+ if (i_iter->jt.type == TGT_NXT) {
+ b_jmp = _gen_bpf_find_nxt(b_iter,
+ i_iter->jt.tgt.nxt);
+ if (b_jmp == NULL)
+ return -EFAULT;
+ i_iter->jt = _BPF_JMP_HSH(b_jmp->hash);
+ }
+ if (i_iter->jf.type == TGT_NXT) {
+ b_jmp = _gen_bpf_find_nxt(b_iter,
+ i_iter->jf.tgt.nxt);
+ if (b_jmp == NULL)
+ return -EFAULT;
+ i_iter->jf = _BPF_JMP_HSH(b_jmp->hash);
+ }
+ /* we shouldn't need to worry about a TGT_NXT in k */
+ }
+ b_iter = b_iter->next;
+ } while (b_iter != NULL && b_iter->next != NULL);
+
+ /* pull in all of the TGT_PTR_HSH jumps, one layer at a time */
+ b_iter = b_tail;
+ do {
+ b_jmp = NULL;
+ /* look for jumps - backwards (shorter jumps) */
+ for (iter = b_iter->blk_cnt - 1;
+ (iter >= 0) && (b_jmp == NULL);
+ iter--) {
+ i_iter = &b_iter->blks[iter];
+ if (i_iter->jt.type == TGT_PTR_HSH)
+ b_jmp = _hsh_find_once(state,
+ i_iter->jt.tgt.hash);
+ if (b_jmp == NULL && i_iter->jf.type == TGT_PTR_HSH)
+ b_jmp = _hsh_find_once(state,
+ i_iter->jf.tgt.hash);
+ if (b_jmp == NULL && i_iter->k.type == TGT_PTR_HSH)
+ b_jmp = _hsh_find_once(state,
+ i_iter->k.tgt.hash);
+ if (b_jmp != NULL) {
+ /* insert the new block after this block */
+ b_jmp->prev = b_iter;
+ b_jmp->next = b_iter->next;
+ b_iter->next = b_jmp;
+ if (b_jmp->next)
+ b_jmp->next->prev = b_jmp;
+ }
+ }
+ if (b_jmp != NULL) {
+ while (b_tail->next != NULL)
+ b_tail = b_tail->next;
+ b_iter = b_tail;
+ } else
+ b_iter = b_iter->prev;
+ } while (b_iter != NULL);
+
+ /* NOTE - from here to the end of the function we need to fail via the
+ * the build_bpf_free_blks label, not just return an error; see
+ * the _gen_bpf_build_jmp() function for details */
+
+ /* check for long jumps and insert if necessary, we also verify that
+ * all our jump targets are valid at this point in the process */
+ b_iter = b_tail;
+ do {
+ res_cnt = 0;
+ for (iter = b_iter->blk_cnt - 1; iter >= 0; iter--) {
+ i_iter = &b_iter->blks[iter];
+ switch (i_iter->jt.type) {
+ case TGT_NONE:
+ case TGT_IMM:
+ break;
+ case TGT_PTR_HSH:
+ h_val = i_iter->jt.tgt.hash;
+ rc = _gen_bpf_build_jmp(state, b_tail,
+ b_iter, iter,
+ h_val);
+ if (rc < 0)
+ goto build_bpf_free_blks;
+ res_cnt += rc;
+ break;
+ default:
+ /* fatal error */
+ goto build_bpf_free_blks;
+ }
+ switch (i_iter->jf.type) {
+ case TGT_NONE:
+ case TGT_IMM:
+ break;
+ case TGT_PTR_HSH:
+ h_val = i_iter->jf.tgt.hash;
+ rc = _gen_bpf_build_jmp(state, b_tail,
+ b_iter, iter,
+ h_val);
+ if (rc < 0)
+ goto build_bpf_free_blks;
+ res_cnt += rc;
+ break;
+ default:
+ /* fatal error */
+ goto build_bpf_free_blks;
+ }
+ }
+ if (res_cnt == 0)
+ b_iter = b_iter->prev;
+ } while (b_iter != NULL);
+
+ /* build the bpf program */
+ do {
+ b_iter = b_head;
+ /* resolve the TGT_PTR_HSH jumps */
+ for (iter = 0; iter < b_iter->blk_cnt; iter++) {
+ i_iter = &b_iter->blks[iter];
+ if (i_iter->jt.type == TGT_PTR_HSH) {
+ h_val = i_iter->jt.tgt.hash;
+ jmp_len = b_iter->blk_cnt - (iter + 1);
+ b_jmp = b_iter->next;
+ while (b_jmp != NULL && b_jmp->hash != h_val) {
+ jmp_len += b_jmp->blk_cnt;
+ b_jmp = b_jmp->next;
+ }
+ if (b_jmp == NULL || jmp_len > _BPF_JMP_MAX)
+ goto build_bpf_free_blks;
+ i_iter->jt = _BPF_JMP_IMM(jmp_len);
+ }
+ if (i_iter->jf.type == TGT_PTR_HSH) {
+ h_val = i_iter->jf.tgt.hash;
+ jmp_len = b_iter->blk_cnt - (iter + 1);
+ b_jmp = b_iter->next;
+ while (b_jmp != NULL && b_jmp->hash != h_val) {
+ jmp_len += b_jmp->blk_cnt;
+ b_jmp = b_jmp->next;
+ }
+ if (b_jmp == NULL || jmp_len > _BPF_JMP_MAX)
+ goto build_bpf_free_blks;
+ i_iter->jf = _BPF_JMP_IMM(jmp_len);
+ }
+ if (i_iter->k.type == TGT_PTR_HSH) {
+ h_val = i_iter->k.tgt.hash;
+ jmp_len = b_iter->blk_cnt - (iter + 1);
+ b_jmp = b_tail;
+ while (b_jmp->hash != h_val)
+ b_jmp = b_jmp->prev;
+ b_jmp = b_jmp->prev;
+ while (b_jmp != b_iter) {
+ jmp_len += b_jmp->blk_cnt;
+ b_jmp = b_jmp->prev;
+ }
+ if (b_jmp == NULL)
+ goto build_bpf_free_blks;
+ i_iter->k = _BPF_K(jmp_len);
+ }
+ }
+
+ /* build the bpf program */
+ if (_bpf_append_blk(state->bpf, b_iter) < 0)
+ goto build_bpf_free_blks;
+
+ /* we're done with the block, free it */
+ b_head = b_iter->next;
+ _blk_free(state, b_iter);
+ } while (b_head != NULL);
+
+ return 0;
+
+build_bpf_free_blks:
+ b_iter = b_head;
+ while (b_iter != NULL) {
+ b_jmp = b_iter->next;
+ _hsh_remove(state, b_iter->hash);
+ __blk_free(state, b_iter);
+ b_iter = b_jmp;
+ }
+ return -EFAULT;
+}
+
+/**
+ * Generate a BPF representation of the filter DB
+ * @param col the seccomp filter collection
+ *
+ * This function generates a BPF representation of the given filter collection.
+ * Returns a pointer to a valid bpf_program on success, NULL on failure.
+ *
+ */
+struct bpf_program *gen_bpf_generate(const struct db_filter_col *col)
+{
+ int rc;
+ struct bpf_state state;
+
+ memset(&state, 0, sizeof(state));
+ state.attr = &col->attr;
+
+ state.bpf = malloc(sizeof(*(state.bpf)));
+ if (state.bpf == NULL)
+ return NULL;
+ memset(state.bpf, 0, sizeof(*(state.bpf)));
+
+ rc = _gen_bpf_build_bpf(&state, col);
+ if (rc < 0)
+ goto bpf_generate_end;
+
+bpf_generate_end:
+ if (rc < 0)
+ _state_release(&state);
+ return state.bpf;
+}
+
+/**
+ * Free memory associated with a BPF representation
+ * @param fprog the BPF representation
+ *
+ * Free the memory associated with a BPF representation generated by the
+ * gen_bpf_generate() function.
+ *
+ */
+void gen_bpf_release(struct bpf_program *program)
+{
+ _program_free(program);
+}
--- /dev/null
+/**
+ * Seccomp BPF Translator
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _TRANSLATOR_BPF_H
+#define _TRANSLATOR_BPF_H
+
+#include <inttypes.h>
+
+#include "arch.h"
+#include "db.h"
+#include "system.h"
+
+/* NOTE - do not change this structure, it is part of the prctl() API */
+struct bpf_program {
+ uint16_t blk_cnt;
+ bpf_instr_raw *blks;
+};
+#define BPF_PGM_SIZE(x) \
+ ((x)->blk_cnt * sizeof(*((x)->blks)))
+
+struct bpf_program *gen_bpf_generate(const struct db_filter_col *col);
+void gen_bpf_release(struct bpf_program *program);
+
+#endif
--- /dev/null
+/**
+ * Seccomp Pseudo Filter Code (PFC) Generator
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* NOTE: needed for the arch->token decoding in _pfc_arch() */
+#include <linux/audit.h>
+
+#include <seccomp.h>
+
+#include "arch.h"
+#include "db.h"
+#include "gen_pfc.h"
+
+struct pfc_sys_list {
+ struct db_sys_list *sys;
+ struct pfc_sys_list *next;
+};
+
+/* XXX - we should check the fprintf() return values */
+
+/**
+ * Display a string representation of the architecture
+ * @param arch the architecture definition
+ */
+static const char *_pfc_arch(const struct arch_def *arch)
+{
+ switch (arch->token) {
+ case SCMP_ARCH_X86:
+ return "x86";
+ case SCMP_ARCH_X86_64:
+ return "x86_64";
+ case SCMP_ARCH_X32:
+ return "x32";
+ case SCMP_ARCH_ARM:
+ return "arm";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+/**
+ * Display a string representation of the node argument
+ * @param fds the file stream to send the output
+ * @param arch the architecture definition
+ * @param node the node
+ */
+static void _pfc_arg(FILE *fds,
+ const struct arch_def *arch,
+ const struct db_arg_chain_tree *node)
+{
+ if (arch->size == ARCH_SIZE_64) {
+ if (arch_arg_offset_hi(arch, node->arg) == node->arg_offset)
+ fprintf(fds, "$a%d.hi32", node->arg);
+ else
+ fprintf(fds, "$a%d.lo32", node->arg);
+ } else
+ fprintf(fds, "$a%d", node->arg);
+}
+
+/**
+ * Display a string representation of the filter action
+ * @param fds the file stream to send the output
+ * @param action the action
+ */
+static void _pfc_action(FILE *fds, uint32_t action)
+{
+ switch (action & 0xffff0000) {
+ case SCMP_ACT_KILL:
+ fprintf(fds, "action KILL;\n");
+ break;
+ case SCMP_ACT_TRAP:
+ fprintf(fds, "action TRAP;\n");
+ break;
+ case SCMP_ACT_ERRNO(0):
+ fprintf(fds, "action ERRNO(%u);\n", (action & 0x0000ffff));
+ break;
+ case SCMP_ACT_TRACE(0):
+ fprintf(fds, "action TRACE(%u);\n", (action & 0x0000ffff));
+ break;
+ case SCMP_ACT_ALLOW:
+ fprintf(fds, "action ALLOW;\n");
+ break;
+ default:
+ fprintf(fds, "action 0x%x;\n", action);
+ }
+}
+
+/**
+ * Indent the output stream
+ * @param fds the file stream to send the output
+ * @param lvl the indentation level
+ *
+ * This function indents the output stream with whitespace based on the
+ * requested indentation level.
+ */
+static void _indent(FILE *fds, unsigned int lvl)
+{
+ while (lvl-- > 0)
+ fprintf(fds, " ");
+}
+
+/**
+ * Generate the pseudo filter code for an argument chain
+ * @param arch the architecture definition
+ * @param node the head of the argument chain
+ * @param lvl the indentation level
+ * @param fds the file stream to send the output
+ *
+ * This function generates the pseudo filter code representation of the given
+ * argument chain and writes it to the given output stream.
+ *
+ */
+static void _gen_pfc_chain(const struct arch_def *arch,
+ const struct db_arg_chain_tree *node,
+ unsigned int lvl, FILE *fds)
+{
+ const struct db_arg_chain_tree *c_iter;
+
+ /* get to the start */
+ c_iter = node;
+ while (c_iter->lvl_prv != NULL)
+ c_iter = c_iter->lvl_prv;
+
+ while (c_iter != NULL) {
+ /* comparison operation */
+ _indent(fds, lvl);
+ fprintf(fds, "if (");
+ _pfc_arg(fds, arch, c_iter);
+ switch (c_iter->op) {
+ case SCMP_CMP_EQ:
+ fprintf(fds, " == ");
+ break;
+ case SCMP_CMP_GE:
+ fprintf(fds, " >= ");
+ break;
+ case SCMP_CMP_GT:
+ fprintf(fds, " > ");
+ break;
+ case SCMP_CMP_MASKED_EQ:
+ fprintf(fds, " & 0x%.8x == ", c_iter->mask);
+ break;
+ default:
+ fprintf(fds, " ??? ");
+ }
+ fprintf(fds, "%u)\n", c_iter->datum);
+
+ /* true result */
+ if (c_iter->act_t_flg) {
+ _indent(fds, lvl + 1);
+ _pfc_action(fds, c_iter->act_t);
+ } else if (c_iter->nxt_t != NULL)
+ _gen_pfc_chain(arch, c_iter->nxt_t, lvl + 1, fds);
+
+ /* false result */
+ if (c_iter->act_f_flg) {
+ _indent(fds, lvl);
+ fprintf(fds, "else\n");
+ _indent(fds, lvl + 1);
+ _pfc_action(fds, c_iter->act_f);
+ } else if (c_iter->nxt_f != NULL) {
+ _indent(fds, lvl);
+ fprintf(fds, "else\n");
+ _gen_pfc_chain(arch, c_iter->nxt_f, lvl + 1, fds);
+ }
+
+ c_iter = c_iter->lvl_nxt;
+ }
+}
+
+/**
+ * Generate pseudo filter code for a syscall
+ * @param arch the architecture definition
+ * @param sys the syscall filter
+ * @param fds the file stream to send the output
+ *
+ * This function generates a pseduo filter code representation of the given
+ * syscall filter and writes it to the given output stream.
+ *
+ */
+static void _gen_pfc_syscall(const struct arch_def *arch,
+ const struct db_sys_list *sys, FILE *fds)
+{
+ unsigned int sys_num = sys->num;
+ const char *sys_name = arch_syscall_resolve_num(arch, sys_num);
+
+ _indent(fds, 1);
+ fprintf(fds, "# filter for syscall \"%s\" (%d) [priority: %d]\n",
+ (sys_name ? sys_name : "UNKNOWN"), sys_num, sys->priority);
+ _indent(fds, 1);
+ fprintf(fds, "if ($syscall == %d)\n", sys_num);
+ if (sys->chains == NULL) {
+ _indent(fds, 2);
+ _pfc_action(fds, sys->action);
+ } else
+ _gen_pfc_chain(arch, sys->chains, 2, fds);
+}
+
+/**
+ * Generate pseudo filter code for an architecture
+ * @param col the seccomp filter collection
+ * @param db the single seccomp filter
+ * @param fds the file stream to send the output
+ *
+ * This function generates a pseudo filter code representation of the given
+ * filter DB and writes it to the given output stream. Returns zero on
+ * success, negative values on failure.
+ *
+ */
+static int _gen_pfc_arch(const struct db_filter_col *col,
+ const struct db_filter *db, FILE *fds)
+{
+ int rc;
+ struct db_sys_list *s_iter;
+ struct pfc_sys_list *p_iter = NULL, *p_new, *p_head = NULL, *p_prev;
+
+ /* sort the syscall list */
+ db_list_foreach(s_iter, db->syscalls) {
+ p_new = malloc(sizeof(*p_new));
+ if (p_new == NULL) {
+ rc = -ENOMEM;
+ goto arch_return;
+ }
+ memset(p_new, 0, sizeof(*p_new));
+ p_new->sys = s_iter;
+
+ p_prev = NULL;
+ p_iter = p_head;
+ while (p_iter != NULL &&
+ s_iter->priority < p_iter->sys->priority) {
+ p_prev = p_iter;
+ p_iter = p_iter->next;
+ }
+ if (p_head == NULL)
+ p_head = p_new;
+ else if (p_prev == NULL) {
+ p_new->next = p_head;
+ p_head = p_new;
+ } else {
+ p_new->next = p_iter;
+ p_prev->next = p_new;
+ }
+ }
+
+ fprintf(fds, "# filter for arch %s (%u)\n",
+ _pfc_arch(db->arch), db->arch->token_bpf);
+ fprintf(fds, "if ($arch == %u)\n", db->arch->token_bpf);
+ p_iter = p_head;
+ while (p_iter != NULL) {
+ if (!p_iter->sys->valid)
+ continue;
+ _gen_pfc_syscall(db->arch, p_iter->sys, fds);
+ p_iter = p_iter->next;
+ }
+ _indent(fds, 1);
+ fprintf(fds, "# default action\n");
+ _indent(fds, 1);
+ _pfc_action(fds, col->attr.act_default);
+
+arch_return:
+ while (p_head != NULL) {
+ p_iter = p_head;
+ p_head = p_head->next;
+ free(p_iter);
+ }
+ return rc;
+}
+
+/**
+ * Generate a pseudo filter code string representation
+ * @param col the seccomp filter collection
+ * @param fd the fd to send the output
+ *
+ * This function generates a pseudo filter code representation of the given
+ * filter collection and writes it to the given fd. Returns zero on success,
+ * negative values on failure.
+ *
+ */
+int gen_pfc_generate(const struct db_filter_col *col, int fd)
+{
+ int rc = 0;
+ int newfd;
+ unsigned int iter;
+ FILE *fds;
+
+ newfd = dup(fd);
+ if (newfd < 0)
+ return errno;
+ fds = fdopen(newfd, "a");
+ if (fds == NULL) {
+ close(newfd);
+ return errno;
+ }
+
+ /* generate the pfc */
+ fprintf(fds, "#\n");
+ fprintf(fds, "# pseudo filter code start\n");
+ fprintf(fds, "#\n");
+
+ for (iter = 0; iter < col->filter_cnt; iter++)
+ _gen_pfc_arch(col, col->filters[iter], fds);
+
+ fprintf(fds, "# invalid architecture action\n");
+ _pfc_action(fds, col->attr.act_badarch);
+ fprintf(fds, "#\n");
+ fprintf(fds, "# pseudo filter code end\n");
+ fprintf(fds, "#\n");
+
+ fflush(fds);
+ fclose(fds);
+
+ return rc;
+}
--- /dev/null
+/**
+ * Seccomp String Translator
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _TRANSLATOR_STR_H
+#define _TRANSLATOR_STR_H
+
+#include "db.h"
+
+int gen_pfc_generate(const struct db_filter_col *col, int fd);
+
+#endif
--- /dev/null
+/**
+ * Seccomp Library hash code
+ *
+ * Release under the Public Domain
+ * Author: Bob Jenkins <bob_jenkins@burtleburtle.net>
+ */
+
+/*
+ * lookup3.c, by Bob Jenkins, May 2006, Public Domain.
+ *
+ * These are functions for producing 32-bit hashes for hash table lookup.
+ * jhash_word(), jhash_le(), jhash_be(), mix(), and final() are externally useful
+ * functions. Routines to test the hash are included if SELF_TEST is defined.
+ * You can use this free for any purpose. It's in the public domain. It has
+ * no warranty.
+ *
+ * You probably want to use jhash_le(). jhash_le() and jhash_be() hash byte
+ * arrays. jhash_le() is is faster than jhash_be() on little-endian machines.
+ * Intel and AMD are little-endian machines.
+ *
+ * If you want to find a hash of, say, exactly 7 integers, do
+ * a = i1; b = i2; c = i3;
+ * mix(a,b,c);
+ * a += i4; b += i5; c += i6;
+ * mix(a,b,c);
+ * a += i7;
+ * final(a,b,c);
+ *
+ * then use c as the hash value. If you have a variable length array of
+ * 4-byte integers to hash, use jhash_word(). If you have a byte array (like
+ * a character string), use jhash_le(). If you have several byte arrays, or
+ * a mix of things, see the comments above jhash_le().
+ *
+ * Why is this so big? I read 12 bytes at a time into 3 4-byte integers, then
+ * mix those integers. This is fast (you can do a lot more thorough mixing
+ * with 12*3 instructions on 3 integers than you can with 3 instructions on 1
+ * byte), but shoehorning those bytes into integers efficiently is messy.
+ */
+
+#include <stdint.h>
+
+#include "arch.h"
+#include "hash.h"
+
+#define hashsize(n) ((uint32_t)1<<(n))
+#define hashmask(n) (hashsize(n)-1)
+#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k))))
+
+/**
+ * Mix 3 32-bit values reversibly
+ * @param a 32-bit value
+ * @param b 32-bit value
+ * @param c 32-bit value
+ *
+ * This is reversible, so any information in (a,b,c) before mix() is still
+ * in (a,b,c) after mix().
+ *
+ * If four pairs of (a,b,c) inputs are run through mix(), or through mix() in
+ * reverse, there are at least 32 bits of the output that are sometimes the
+ * same for one pair and different for another pair.
+ *
+ * This was tested for:
+ * - pairs that differed by one bit, by two bits, in any combination of top
+ * bits of (a,b,c), or in any combination of bottom bits of (a,b,c).
+ * - "differ" is defined as +, -, ^, or ~^. For + and -, I transformed the
+ * output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly
+ * produced by subtraction) look like a single 1-bit difference.
+ * - the base values were pseudorandom, all zero but one bit set, or all zero
+ * plus a counter that starts at zero.
+ *
+ * Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that
+ * satisfy this are
+ * 4 6 8 16 19 4
+ * 9 15 3 18 27 15
+ * 14 9 3 7 17 3
+ *
+ * Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing for "differ"
+ * defined as + with a one-bit base and a two-bit delta. I used
+ * http://burtleburtle.net/bob/hash/avalanche.html to choose the operations,
+ * constants, and arrangements of the variables.
+ *
+ * This does not achieve avalanche. There are input bits of (a,b,c) that fail
+ * to affect some output bits of (a,b,c), especially of a. The most thoroughly
+ * mixed value is c, but it doesn't really even achieve avalanche in c.
+ *
+ * This allows some parallelism. Read-after-writes are good at doubling the
+ * number of bits affected, so the goal of mixing pulls in the opposite
+ * direction as the goal of parallelism. I did what I could. Rotates seem to
+ * cost as much as shifts on every machine I could lay my hands on, and rotates
+ * are much kinder to the top and bottom bits, so I used rotates.
+ *
+ */
+#define mix(a,b,c) \
+ { \
+ a -= c; a ^= rot(c, 4); c += b; \
+ b -= a; b ^= rot(a, 6); a += c; \
+ c -= b; c ^= rot(b, 8); b += a; \
+ a -= c; a ^= rot(c,16); c += b; \
+ b -= a; b ^= rot(a,19); a += c; \
+ c -= b; c ^= rot(b, 4); b += a; \
+ }
+
+/**
+ * Final mixing of 3 32-bit values (a,b,c) into c
+ * @param a 32-bit value
+ * @param b 32-bit value
+ * @param c 32-bit value
+ *
+ * Pairs of (a,b,c) values differing in only a few bits will usually produce
+ * values of c that look totally different. This was tested for:
+ * - pairs that differed by one bit, by two bits, in any combination of top
+ * bits of (a,b,c), or in any combination of bottom bits of (a,b,c).
+ * - "differ" is defined as +, -, ^, or ~^. For + and -, I transformed the
+ * output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly
+ * produced by subtraction) look like a single 1-bit difference.
+ * - the base values were pseudorandom, all zero but one bit set, or all zero
+ * plus a counter that starts at zero.
+ *
+ * These constants passed:
+ * 14 11 25 16 4 14 24
+ * 12 14 25 16 4 14 24
+ * and these came close:
+ * 4 8 15 26 3 22 24
+ * 10 8 15 26 3 22 24
+ * 11 8 15 26 3 22 24
+ *
+ */
+#define final(a,b,c) \
+ { \
+ c ^= b; c -= rot(b,14); \
+ a ^= c; a -= rot(c,11); \
+ b ^= a; b -= rot(a,25); \
+ c ^= b; c -= rot(b,16); \
+ a ^= c; a -= rot(c,4); \
+ b ^= a; b -= rot(a,14); \
+ c ^= b; c -= rot(b,24); \
+ }
+
+/**
+ * Hash an array of 32-bit values
+ * @param k the key, an array of uint32_t values
+ * @param length the number of array elements
+ * @param initval the previous hash, or an arbitrary value
+ *
+ * This works on all machines. To be useful, it requires:
+ * - that the key be an array of uint32_t's, and
+ * - that the length be the number of uint32_t's in the key
+ *
+ * The function jhash_word() is identical to jhash_le() on little-endian
+ * machines, and identical to jhash_be() on big-endian machines, except that
+ * the length has to be measured in uint32_ts rather than in bytes. jhash_le()
+ * is more complicated than jhash_word() only because jhash_le() has to dance
+ * around fitting the key bytes into registers.
+ *
+ */
+static uint32_t jhash_word(const uint32_t *k, size_t length, uint32_t initval)
+{
+ uint32_t a, b, c;
+
+ /* set up the internal state */
+ a = b = c = 0xdeadbeef + (((uint32_t)length) << 2) + initval;
+
+ /* handle most of the key */
+ while (length > 3) {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a, b, c);
+ length -= 3;
+ k += 3;
+ }
+
+ /* handle the last 3 uint32_t's */
+ switch(length) {
+ case 3 :
+ c += k[2];
+ case 2 :
+ b += k[1];
+ case 1 :
+ a += k[0];
+ final(a, b, c);
+ case 0:
+ /* nothing left to add */
+ break;
+ }
+
+ return c;
+}
+
+/**
+ * Hash a variable-length key into a 32-bit value
+ * @param k the key (the unaligned variable-length array of bytes)
+ * @param length the length of the key, counting by bytes
+ * @param initval can be any 4-byte value
+ *
+ * Returns a 32-bit value. Every bit of the key affects every bit of the
+ * return value. Two keys differing by one or two bits will have totally
+ * different hash values.
+ *
+ * The best hash table sizes are powers of 2. There is no need to do mod a
+ * prime (mod is sooo slow!). If you need less than 32 bits, use a bitmask.
+ * For example, if you need only 10 bits, do:
+ * h = (h & hashmask(10));
+ * In which case, the hash table should have hashsize(10) elements.
+ *
+ * If you are hashing n strings (uint8_t **)k, do it like this:
+ * for (i=0, h=0; i<n; ++i) h = jhash_le( k[i], len[i], h);
+ *
+ */
+static uint32_t jhash_le(const void *key, size_t length, uint32_t initval)
+{
+ uint32_t a, b, c;
+ union {
+ const void *ptr;
+ size_t i;
+ } u; /* needed for Mac Powerbook G4 */
+
+ /* set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
+
+ u.ptr = key;
+ if ((arch_def_native->endian == ARCH_ENDIAN_LITTLE) &&
+ ((u.i & 0x3) == 0)) {
+ /* read 32-bit chunks */
+ const uint32_t *k = (const uint32_t *)key;
+
+ while (length > 12) {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a, b, c);
+ length -= 12;
+ k += 3;
+ }
+
+ /* "k[2]&0xffffff" actually reads beyond the end of the string,
+ * but then masks off the part it's not allowed to read.
+ * Because the string is aligned, the masked-off tail is in the
+ * same word as the rest of the string. Every machine with
+ * memory protection I've seen does it on word boundaries, so
+ * is OK with this. But VALGRIND will still catch it and
+ * complain. The masking trick does make the hash noticably
+ * faster for short strings (like English words). */
+#ifndef VALGRIND
+
+ switch(length) {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += k[2] & 0xffffff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 10:
+ c += k[2] & 0xffff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 9 :
+ c += k[2] & 0xff;
+ b += k[1];
+ a += k[0];
+ break;
+ case 8 :
+ b += k[1];
+ a += k[0];
+ break;
+ case 7 :
+ b += k[1] & 0xffffff;
+ a += k[0];
+ break;
+ case 6 :
+ b += k[1] & 0xffff;
+ a += k[0];
+ break;
+ case 5 :
+ b += k[1] & 0xff;
+ a += k[0];
+ break;
+ case 4 :
+ a += k[0];
+ break;
+ case 3 :
+ a += k[0] & 0xffffff;
+ break;
+ case 2 :
+ a += k[0] & 0xffff;
+ break;
+ case 1 :
+ a += k[0] & 0xff;
+ break;
+ case 0 :
+ /* zero length strings require no mixing */
+ return c;
+ }
+
+#else /* make valgrind happy */
+
+ k8 = (const uint8_t *)k;
+ switch(length) {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += ((uint32_t)k8[10]) << 16;
+ case 10:
+ c += ((uint32_t)k8[9]) << 8;
+ case 9 :
+ c += k8[8];
+ case 8 :
+ b += k[1];
+ a += k[0];
+ break;
+ case 7 :
+ b += ((uint32_t)k8[6]) << 16;
+ case 6 :
+ b += ((uint32_t)k8[5]) << 8;
+ case 5 :
+ b += k8[4];
+ case 4 :
+ a += k[0];
+ break;
+ case 3 :
+ a += ((uint32_t)k8[2]) << 16;
+ case 2 :
+ a += ((uint32_t)k8[1]) << 8;
+ case 1 :
+ a += k8[0];
+ break;
+ case 0 :
+ return c;
+ }
+
+#endif /* !valgrind */
+
+ } else if ((arch_def_native->endian == ARCH_ENDIAN_LITTLE) &&
+ ((u.i & 0x1) == 0)) {
+ /* read 16-bit chunks */
+ const uint16_t *k = (const uint16_t *)key;
+ const uint8_t *k8;
+
+ while (length > 12) {
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ b += k[2] + (((uint32_t)k[3]) << 16);
+ c += k[4] + (((uint32_t)k[5]) << 16);
+ mix(a, b, c);
+ length -= 12;
+ k += 6;
+ }
+
+ k8 = (const uint8_t *)k;
+ switch(length) {
+ case 12:
+ c += k[4] + (((uint32_t)k[5]) << 16);
+ b += k[2] + (((uint32_t)k[3]) << 16);
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 11:
+ c += ((uint32_t)k8[10]) << 16;
+ case 10:
+ c += k[4];
+ b += k[2] + (((uint32_t)k[3]) << 16);
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 9 :
+ c += k8[8];
+ case 8 :
+ b += k[2] + (((uint32_t)k[3]) << 16);
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 7 :
+ b += ((uint32_t)k8[6]) << 16;
+ case 6 :
+ b += k[2];
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 5 :
+ b += k8[4];
+ case 4 :
+ a += k[0] + (((uint32_t)k[1]) << 16);
+ break;
+ case 3 :
+ a += ((uint32_t)k8[2]) << 16;
+ case 2 :
+ a += k[0];
+ break;
+ case 1 :
+ a += k8[0];
+ break;
+ case 0 :
+ /* zero length requires no mixing */
+ return c;
+ }
+
+ } else {
+ /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ while (length > 12) {
+ a += k[0];
+ a += ((uint32_t)k[1]) << 8;
+ a += ((uint32_t)k[2]) << 16;
+ a += ((uint32_t)k[3]) << 24;
+ b += k[4];
+ b += ((uint32_t)k[5]) << 8;
+ b += ((uint32_t)k[6]) << 16;
+ b += ((uint32_t)k[7]) << 24;
+ c += k[8];
+ c += ((uint32_t)k[9]) << 8;
+ c += ((uint32_t)k[10]) << 16;
+ c += ((uint32_t)k[11]) << 24;
+ mix(a, b, c);
+ length -= 12;
+ k += 12;
+ }
+
+ switch(length) {
+ case 12:
+ c += ((uint32_t)k[11]) << 24;
+ case 11:
+ c += ((uint32_t)k[10]) << 16;
+ case 10:
+ c += ((uint32_t)k[9]) << 8;
+ case 9 :
+ c += k[8];
+ case 8 :
+ b += ((uint32_t)k[7]) << 24;
+ case 7 :
+ b += ((uint32_t)k[6]) << 16;
+ case 6 :
+ b += ((uint32_t)k[5]) << 8;
+ case 5 :
+ b += k[4];
+ case 4 :
+ a += ((uint32_t)k[3]) << 24;
+ case 3 :
+ a += ((uint32_t)k[2]) << 16;
+ case 2 :
+ a += ((uint32_t)k[1]) << 8;
+ case 1 :
+ a += k[0];
+ break;
+ case 0 :
+ return c;
+ }
+ }
+
+ final(a, b, c);
+ return c;
+}
+
+/**
+ * Hash a variable-length key into a 32-bit value
+ * @param k the key (the unaligned variable-length array of bytes)
+ * @param length the length of the key, counting by bytes
+ * @param initval can be any 4-byte value
+ *
+ * This is the same as jhash_word() on big-endian machines. It is different
+ * from jhash_le() on all machines. jhash_be() takes advantage of big-endian
+ * byte ordering.
+ *
+ */
+static uint32_t jhash_be( const void *key, size_t length, uint32_t initval)
+{
+ uint32_t a, b, c;
+ union {
+ const void *ptr;
+ size_t i;
+ } u; /* to cast key to (size_t) happily */
+
+ /* set up the internal state */
+ a = b = c = 0xdeadbeef + ((uint32_t)length) + initval;
+
+ u.ptr = key;
+ if ((arch_def_native->endian == ARCH_ENDIAN_BIG) &&
+ ((u.i & 0x3) == 0)) {
+ /* read 32-bit chunks */
+ const uint32_t *k = (const uint32_t *)key;
+
+ while (length > 12) {
+ a += k[0];
+ b += k[1];
+ c += k[2];
+ mix(a, b, c);
+ length -= 12;
+ k += 3;
+ }
+
+ /* "k[2]<<8" actually reads beyond the end of the string, but
+ * then shifts out the part it's not allowed to read. Because
+ * the string is aligned, the illegal read is in the same word
+ * as the rest of the string. Every machine with memory
+ * protection I've seen does it on word boundaries, so is OK
+ * with this. But VALGRIND will still catch it and complain.
+ * The masking trick does make the hash noticably faster for
+ * short strings (like English words). */
+#ifndef VALGRIND
+
+ switch(length) {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += k[2] & 0xffffff00;
+ b += k[1];
+ a += k[0];
+ break;
+ case 10:
+ c += k[2] & 0xffff0000;
+ b += k[1];
+ a += k[0];
+ break;
+ case 9 :
+ c += k[2] & 0xff000000;
+ b += k[1];
+ a += k[0];
+ break;
+ case 8 :
+ b += k[1];
+ a += k[0];
+ break;
+ case 7 :
+ b += k[1] & 0xffffff00;
+ a += k[0];
+ break;
+ case 6 :
+ b += k[1] & 0xffff0000;
+ a += k[0];
+ break;
+ case 5 :
+ b += k[1] & 0xff000000;
+ a += k[0];
+ break;
+ case 4 :
+ a += k[0];
+ break;
+ case 3 :
+ a += k[0] & 0xffffff00;
+ break;
+ case 2 :
+ a += k[0] & 0xffff0000;
+ break;
+ case 1 :
+ a += k[0] & 0xff000000;
+ break;
+ case 0 :
+ /* zero length strings require no mixing */
+ return c;
+ }
+
+#else /* make valgrind happy */
+
+ k8 = (const uint8_t *)k;
+ switch(length) {
+ case 12:
+ c += k[2];
+ b += k[1];
+ a += k[0];
+ break;
+ case 11:
+ c += ((uint32_t)k8[10]) << 8;
+ case 10:
+ c += ((uint32_t)k8[9]) << 16;
+ case 9 :
+ c += ((uint32_t)k8[8]) << 24;
+ case 8 :
+ b += k[1];
+ a += k[0];
+ break;
+ case 7 :
+ b += ((uint32_t)k8[6]) << 8;
+ case 6 :
+ b += ((uint32_t)k8[5]) << 16;
+ case 5 :
+ b += ((uint32_t)k8[4]) << 24;
+ case 4 :
+ a += k[0];
+ break;
+ case 3 :
+ a += ((uint32_t)k8[2]) << 8;
+ case 2 :
+ a += ((uint32_t)k8[1]) << 16;
+ case 1 :
+ a += ((uint32_t)k8[0]) << 24;
+ break;
+ case 0 :
+ return c;
+ }
+
+#endif /* !VALGRIND */
+
+ } else {
+ /* need to read the key one byte at a time */
+ const uint8_t *k = (const uint8_t *)key;
+
+ while (length > 12) {
+ a += ((uint32_t)k[0]) << 24;
+ a += ((uint32_t)k[1]) << 16;
+ a += ((uint32_t)k[2]) << 8;
+ a += ((uint32_t)k[3]);
+ b += ((uint32_t)k[4]) << 24;
+ b += ((uint32_t)k[5]) << 16;
+ b += ((uint32_t)k[6]) << 8;
+ b += ((uint32_t)k[7]);
+ c += ((uint32_t)k[8]) << 24;
+ c += ((uint32_t)k[9]) << 16;
+ c += ((uint32_t)k[10]) << 8;
+ c += ((uint32_t)k[11]);
+ mix(a, b, c);
+ length -= 12;
+ k += 12;
+ }
+
+ switch(length) {
+ case 12:
+ c += k[11];
+ case 11:
+ c += ((uint32_t)k[10]) << 8;
+ case 10:
+ c += ((uint32_t)k[9]) << 16;
+ case 9 :
+ c += ((uint32_t)k[8]) << 24;
+ case 8 :
+ b += k[7];
+ case 7 :
+ b += ((uint32_t)k[6]) << 8;
+ case 6 :
+ b += ((uint32_t)k[5]) << 16;
+ case 5 :
+ b += ((uint32_t)k[4]) << 24;
+ case 4 :
+ a += k[3];
+ case 3 :
+ a += ((uint32_t)k[2]) << 8;
+ case 2 :
+ a += ((uint32_t)k[1]) << 16;
+ case 1 :
+ a += ((uint32_t)k[0]) << 24;
+ break;
+ case 0 :
+ return c;
+ }
+ }
+
+ final(a, b, c);
+ return c;
+}
+
+/**
+ * Hash a variable-length key into a 32-bit value
+ * @param k the key (the unaligned variable-length array of bytes)
+ * @param length the length of the key, counting by bytes
+ * @param initval can be any 4-byte value
+ *
+ * A small wrapper function that selects the proper hash function based on the
+ * native machine's byte-ordering.
+ *
+ */
+uint32_t jhash(const void *key, size_t length, uint32_t initval)
+{
+ if (length % sizeof(uint32_t) == 0)
+ return jhash_word(key, (length / sizeof(uint32_t)), initval);
+ else if (arch_def_native->endian == ARCH_ENDIAN_BIG)
+ return jhash_be(key, length, initval);
+ else
+ return jhash_le(key, length, initval);
+}
--- /dev/null
+/**
+ * The "lookup3.c" Hash Implementation from Bob Jenkins
+ *
+ * Original Author: Bob Jenkins <bob_jenkins@burtleburtle.net>
+ * Source: http://burtleburtle.net/bob/c/lookup3.c
+ */
+
+/*
+ * Original License:
+ *
+ * These are functions for producing 32-bit hashes for hash table lookup.
+ * hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final()
+ * are externally useful functions. Routines to test the hash are included
+ * if SELF_TEST is defined. You can use this free for any purpose. It's in
+ * the public domain. It has no warranty.
+ */
+
+#ifndef _HASH_H
+#define _HASH_H
+
+#include <inttypes.h>
+
+uint32_t jhash(const void *key, size_t length, uint32_t initval);
+
+#endif
+
--- /dev/null
+#
+# Enhanced Seccomp Library Python Bindings Makefile
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+#
+# macros
+#
+
+include ../../macros.mk
+
+#
+# configuration
+#
+
+include $(TOPDIR)/version_info.mk
+include $(TOPDIR)/configure.mk
+include $(TOPDIR)/install.mk
+
+LIB_STATIC = ../libseccomp.a
+
+#
+# targets
+#
+
+.PHONY: all install clean
+
+all: build
+
+build: $(LIB_STATIC) libseccomp.pxd seccomp.pyx
+ @$(RM) seccomp.c
+ $(PY_BUILD) && touch build
+
+install: build
+ $(PY_INSTALL) install --prefix=$(DESTDIR)/$(INSTALL_PREFIX)
+
+clean:
+ $(RM) -rf build seccomp.c
--- /dev/null
+#
+# Seccomp Library Python Bindings
+#
+# Copyright (c) 2012,2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 uint8_t, uint32_t, uint64_t
+
+cdef extern from "seccomp.h":
+
+ ctypedef void* scmp_filter_ctx
+
+ cdef enum:
+ SCMP_ARCH_NATIVE
+ SCMP_ARCH_X86
+ SCMP_ARCH_X86_64
+ SCMP_ARCH_X32
+ SCMP_ARCH_ARM
+
+ cdef enum scmp_filter_attr:
+ SCMP_FLTATR_ACT_DEFAULT
+ SCMP_FLTATR_ACT_BADARCH
+ SCMP_FLTATR_CTL_NNP
+
+ 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
+ SCMP_ACT_TRAP
+ SCMP_ACT_ALLOW
+ 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
+
+ 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_native()
+ int seccomp_arch_exist(scmp_filter_ctx ctx, uint32_t arch_token)
+ int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)
+ int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t 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(uint32_t arch_token, int num)
+ int seccomp_syscall_resolve_name_arch(uint32_t 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_exact(scmp_filter_ctx ctx, uint32_t action,
+ int syscall, unsigned int arg_cnt, ...)
+
+ 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;
--- /dev/null
+#
+# Seccomp Library Python Bindings
+#
+# Copyright (c) 2012,2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+""" 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 - kill the process
+ ALLOW - allow the syscall to execute
+ TRAP - a SIGSYS signal will be thrown
+ 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_b) == datum_a
+
+
+Example:
+
+ import sys
+ from seccomp import *
+
+ # create a filter object with a default KILL action
+ f = SyscallFilter(defaction=KILL)
+
+ # 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))
+ f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout))
+ f.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr))
+ f.add_rule(ALLOW, "rt_sigreturn")
+
+ # load the filter into the kernel
+ f.load()
+"""
+__author__ = 'Paul Moore <paul@paul-moore.com>'
+__date__ = "7 January 2013"
+
+from libc.stdint cimport uint32_t
+import errno
+
+cimport libseccomp
+
+KILL = libseccomp.SCMP_ACT_KILL
+TRAP = libseccomp.SCMP_ACT_TRAP
+ALLOW = libseccomp.SCMP_ACT_ALLOW
+def ERRNO(int errno):
+ return libseccomp.SCMP_ACT_ERRNO(errno)
+def TRACE(int value):
+ 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.
+ """
+ if (isinstance(syscall, basestring)):
+ return libseccomp.seccomp_syscall_resolve_name_arch(arch, syscall)
+ elif (isinstance(syscall, int)):
+ return libseccomp.seccomp_syscall_resolve_num_arch(arch, syscall)
+ else:
+ raise TypeError("Syscall must either be an int or str type")
+
+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
+ """
+
+ 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
+
+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
+ """
+ ACT_DEFAULT = libseccomp.SCMP_FLTATR_ACT_DEFAULT
+ ACT_BADARCH = libseccomp.SCMP_FLTATR_ACT_BADARCH
+ CTL_NNP = libseccomp.SCMP_FLTATR_CTL_NNP
+
+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 arguement 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
+
+ def 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 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.
+ """
+ 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, TRAP, ERRNO(), TRACE(), 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 """
+ 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, TRAP, ERRNO(), TRACE(), 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 """
+ 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 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
+
+ Output the filter in Berkley 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;
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Enhanced Seccomp Library Python Module Build Script
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 = "http://libseccomp.sf.net",
+ 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"],
+ extra_objects=["../libseccomp.a"])
+ ]
+)
--- /dev/null
+/**
+ * Seccomp System Information
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _SYSTEM_H
+#define _SYSTEM_H
+
+#include <linux/filter.h>
+#include <linux/prctl.h>
+
+#include <configure.h>
+
+#ifdef CONF_SYSINC_SECCOMP
+
+/* system header file */
+#include <linux/seccomp.h>
+
+#else
+
+/* NOTE: the definitions below were taken from the Linux Kernel sources */
+#include <linux/types.h>
+
+/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
+#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */
+#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
+#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
+
+/*
+ * All BPF programs must return a 32-bit value.
+ * The bottom 16-bits are for optional return data.
+ * The upper 16-bits are ordered from least permissive values to most.
+ *
+ * The ordering ensures that a min_t() over composed return values always
+ * selects the least permissive choice.
+ */
+#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
+#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
+#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
+#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
+#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
+
+/* Masks for the return value sections. */
+#define SECCOMP_RET_ACTION 0x7fff0000U
+#define SECCOMP_RET_DATA 0x0000ffffU
+
+/*
+ * struct seccomp_data - the format the BPF program executes over.
+ * @nr: the system call number
+ * @arch: indicates system call convention as an AUDIT_ARCH_* value
+ * as defined in <linux/audit.h>.
+ * @instruction_pointer: at the time of the system call.
+ * @args: up to 6 system call arguments always stored as 64-bit values
+ * regardless of the architecture.
+ */
+struct seccomp_data {
+ int nr;
+ __u32 arch;
+ __u64 instruction_pointer;
+ __u64 args[6];
+};
+
+#endif /* CONF_SYSINC_SECCOMP */
+
+/* rename some of the socket filter types to make more sense */
+typedef struct sock_filter bpf_instr_raw;
+
+#ifndef PR_SET_NO_NEW_PRIVS
+#define PR_SET_NO_NEW_PRIVS 38
+#endif /* PR_SET_NO_NEW_PRIVS */
+
+#ifndef PR_GET_NO_NEW_PRIVS
+#define PR_GET_NO_NEW_PRIVS 39
+#endif /* PR_GET_NO_NEW_PRIVS */
+
+#endif
--- /dev/null
+!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
+!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
+!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
+!_TAG_PROGRAM_NAME Exuberant Ctags //
+!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
+!_TAG_PROGRAM_VERSION 5.8 //
+ACT_BADARCH src/python/seccomp.pyx /^ ACT_BADARCH = libseccomp.SCMP_FLTATR_ACT_BADARCH$/;" v class:Attr
+ACT_DEFAULT src/python/seccomp.pyx /^ ACT_DEFAULT = libseccomp.SCMP_FLTATR_ACT_DEFAULT$/;" v class:Attr
+ADDDEP macros.mk /^ADDDEP = \\$/;" m
+AINC_BLK src/gen_bpf.c 39;" d file:
+AINC_PROG src/gen_bpf.c 40;" d file:
+ALLOW src/python/seccomp.pyx /^ALLOW = libseccomp.SCMP_ACT_ALLOW$/;" v
+ARCHIVE macros.mk /^ ARCHIVE = @echo " AR $@";$/;" m
+ARCH_ENDIAN_BIG src/arch.h /^ ARCH_ENDIAN_BIG,$/;" e enum:arch_def::__anon3
+ARCH_ENDIAN_LITTLE src/arch.h /^ ARCH_ENDIAN_LITTLE,$/;" e enum:arch_def::__anon3
+ARCH_ENDIAN_UNSPEC src/arch.h /^ ARCH_ENDIAN_UNSPEC = 0,$/;" e enum:arch_def::__anon3
+ARCH_SIZE_32 src/arch.h /^ ARCH_SIZE_32 = 32,$/;" e enum:arch_def::__anon2
+ARCH_SIZE_64 src/arch.h /^ ARCH_SIZE_64 = 64,$/;" e enum:arch_def::__anon2
+ARCH_SIZE_UNSPEC src/arch.h /^ ARCH_SIZE_UNSPEC = 0,$/;" e enum:arch_def::__anon2
+ARG_COUNT_MAX src/arch.h 76;" d
+ARG_MASK_MAX src/db.h 70;" d
+ARM src/python/seccomp.pyx /^ ARM = libseccomp.SCMP_ARCH_ARM$/;" v class:Arch
+AWK macros.mk /^AWK ?= awk$/;" m
+Arch src/python/seccomp.pyx /^cdef class Arch:$/;" c
+Arg src/python/seccomp.pyx /^cdef class Arg:$/;" c
+Attr src/python/seccomp.pyx /^cdef class Attr:$/;" c
+BINDINGS src/Makefile /^BINDINGS =$/;" m
+BPF_A tools/bpf.h 117;" d
+BPF_ABS tools/bpf.h 87;" d
+BPF_ADD tools/bpf.h 95;" d
+BPF_ALU tools/bpf.h 75;" d
+BPF_AND tools/bpf.h 100;" d
+BPF_B tools/bpf.h 84;" d
+BPF_CLASS tools/bpf.h 70;" d
+BPF_DIV tools/bpf.h 98;" d
+BPF_H tools/bpf.h 83;" d
+BPF_IMM tools/bpf.h 86;" d
+BPF_IND tools/bpf.h 88;" d
+BPF_JA tools/bpf.h 105;" d
+BPF_JEQ tools/bpf.h 106;" d
+BPF_JGE tools/bpf.h 108;" d
+BPF_JGT tools/bpf.h 107;" d
+BPF_JMP tools/bpf.h 76;" d
+BPF_JSET tools/bpf.h 109;" d
+BPF_K tools/bpf.h 112;" d
+BPF_LD tools/bpf.h 71;" d
+BPF_LDX tools/bpf.h 72;" d
+BPF_LEN tools/bpf.h 90;" d
+BPF_LSH tools/bpf.h 101;" d
+BPF_MEM tools/bpf.h 89;" d
+BPF_MISC tools/bpf.h 78;" d
+BPF_MISCOP tools/bpf.h 120;" d
+BPF_MODE tools/bpf.h 85;" d
+BPF_MSH tools/bpf.h 91;" d
+BPF_MUL tools/bpf.h 97;" d
+BPF_NEG tools/bpf.h 103;" d
+BPF_OP tools/bpf.h 93;" d
+BPF_OR tools/bpf.h 99;" d
+BPF_PGM_SIZE src/gen_bpf.h 36;" d
+BPF_PRG_MAX_LEN tools/scmp_bpf_sim.c 36;" d file:
+BPF_RET tools/bpf.h 77;" d
+BPF_RSH tools/bpf.h 102;" d
+BPF_RVAL tools/bpf.h 116;" d
+BPF_SCRATCH_SIZE tools/bpf.h 33;" d
+BPF_SIZE tools/bpf.h 81;" d
+BPF_SRC tools/bpf.h 111;" d
+BPF_ST tools/bpf.h 73;" d
+BPF_STX tools/bpf.h 74;" d
+BPF_SUB tools/bpf.h 96;" d
+BPF_SYSCALL_MAX tools/bpf.h 45;" d
+BPF_SYS_ARG_MAX tools/bpf.h 38;" d
+BPF_TAX tools/bpf.h 121;" d
+BPF_TXA tools/bpf.h 122;" d
+BPF_W tools/bpf.h 82;" d
+BPF_X tools/bpf.h 113;" d
+CAT macros.mk /^CAT ?= cat$/;" m
+CFLAGS macros.mk /^CFLAGS ?= -Wl,-z,relro -Wall -O0 -g$/;" m
+COMPILE macros.mk /^ COMPILE = @echo " CC $@";$/;" m
+COMPILE_EXEC macros.mk /^ COMPILE_EXEC = @echo " CC $@";$/;" m
+CONFIGS Makefile /^CONFIGS = configure.mk configure.h version_info.mk libseccomp.pc$/;" m
+CONF_BINDINGS_PYTHON configure.h 8;" d
+CONF_BINDINGS_PYTHON configure.mk /^CONF_BINDINGS_PYTHON = 1$/;" m
+CONF_INSTALL_LIBDIR configure.mk /^CONF_INSTALL_LIBDIR = "\/usr\/local\/lib"$/;" m
+CONF_INSTALL_PREFIX configure.mk /^CONF_INSTALL_PREFIX = "\/usr\/local"$/;" m
+CONF_SYSINC_SECCOMP configure.h 7;" d
+CONF_SYSINC_SECCOMP configure.mk /^CONF_SYSINC_SECCOMP = 1$/;" m
+CTL_NNP src/python/seccomp.pyx /^ CTL_NNP = libseccomp.SCMP_FLTATR_CTL_NNP$/;" v class:Attr
+D64_HI src/arch.h 74;" d
+D64_LO src/arch.h 73;" d
+DATUM_MAX src/arch.h 72;" d
+DEPS src/Makefile /^DEPS = $(OBJS:%.o=%.d)$/;" m
+DEPS tools/Makefile /^DEPS = $(TOOLS:%=%.d)$/;" m
+DEPS_OBJS tests/Makefile /^DEPS_OBJS = $(OBJS:%.o=%.d)$/;" m
+DEPS_TESTS tests/Makefile /^DEPS_TESTS = $(TESTS:%=%.d)$/;" m
+ECHO macros.mk /^ECHO ?= echo$/;" m
+ECHO_INFO macros.mk /^ ECHO_INFO ?= $(ECHO) ">> INFO:"$/;" m
+ECHO_INFO macros.mk /^ ECHO_INFO ?= \/bin\/true || $(ECHO) ">> INFO:"$/;" m
+EQ src/python/seccomp.pyx /^EQ = libseccomp.SCMP_CMP_EQ$/;" v
+ERRNO src/python/seccomp.pyx /^def ERRNO(int errno):$/;" f
+Extension src/python/setup.py /^from distutils.extension import Extension$/;" i
+GCC macros.mk /^GCC ?= gcc$/;" m
+GE src/python/seccomp.pyx /^GE = libseccomp.SCMP_CMP_GE$/;" v
+GT src/python/seccomp.pyx /^GT = libseccomp.SCMP_CMP_GT$/;" v
+HASH_BIG_ENDIAN src/hash.c 55;" d file:
+HASH_BIG_ENDIAN src/hash.c 60;" d file:
+HASH_BIG_ENDIAN src/hash.c 63;" d file:
+HASH_LITTLE_ENDIAN src/hash.c 54;" d file:
+HASH_LITTLE_ENDIAN src/hash.c 59;" d file:
+HASH_LITTLE_ENDIAN src/hash.c 62;" d file:
+HDR_BUILD include/Makefile /^HDR_BUILD = seccomp.h$/;" m
+INSTALL macros.mk /^INSTALL ?= install$/;" m
+INSTALL_BIN_DIR install.mk /^INSTALL_BIN_DIR ?= $(DESTDIR)\/$(INSTALL_PREFIX)\/bin$/;" m
+INSTALL_BIN_MACRO macros.mk /^ INSTALL_BIN_MACRO = @echo " INSTALL $^ ($(INSTALL_BIN_DIR)\/$^)";$/;" m
+INSTALL_GROUP install.mk /^INSTALL_GROUP ?= $$(id -g)$/;" m
+INSTALL_INC_DIR install.mk /^INSTALL_INC_DIR ?= $(DESTDIR)\/$(INSTALL_PREFIX)\/include$/;" m
+INSTALL_INC_MACRO macros.mk /^ INSTALL_INC_MACRO = @echo " INSTALL $^ ($(INSTALL_INC_DIR))";$/;" m
+INSTALL_LIB_DIR install.mk /^INSTALL_LIB_DIR ?= $(DESTDIR)\/$(CONF_INSTALL_LIBDIR)$/;" m
+INSTALL_LIB_MACRO macros.mk /^ INSTALL_LIB_MACRO = @echo " INSTALL $^ ($(INSTALL_LIB_DIR)\/$^)";$/;" m
+INSTALL_MAN1_MACRO macros.mk /^ INSTALL_MAN1_MACRO = \\$/;" m
+INSTALL_MAN3_MACRO macros.mk /^ INSTALL_MAN3_MACRO = \\$/;" m
+INSTALL_MAN_DIR install.mk /^INSTALL_MAN_DIR ?= $(DESTDIR)\/$(INSTALL_PREFIX)\/share\/man$/;" m
+INSTALL_OWNER install.mk /^INSTALL_OWNER ?= $$(id -u)$/;" m
+INSTALL_PC_MACRO macros.mk /^ INSTALL_PC_MACRO = \\$/;" m
+INSTALL_PREFIX install.mk /^INSTALL_PREFIX ?= $(CONF_INSTALL_PREFIX)$/;" m
+INSTALL_SBIN_DIR install.mk /^INSTALL_SBIN_DIR ?= $(DESTDIR)\/$(INSTALL_PREFIX)\/sbin$/;" m
+KILL src/python/seccomp.pyx /^KILL = libseccomp.SCMP_ACT_KILL$/;" v
+LDFLAGS macros.mk /^LDFLAGS ?= -z relro -g$/;" m
+LDFLAGS tests/Makefile /^LDFLAGS := ..\/src\/libseccomp.a $(OBJS)$/;" m
+LDFLAGS tools/Makefile /^LDFLAGS := ..\/src\/libseccomp.a$/;" m
+LE src/python/seccomp.pyx /^LE = libseccomp.SCMP_CMP_LE$/;" v
+LIBFLAGS macros.mk /^LIBFLAGS =$/;" m
+LIB_SHARED src/Makefile /^LIB_SHARED = libseccomp.so.$(VERSION_RELEASE)$/;" m
+LIB_STATIC src/Makefile /^LIB_STATIC = libseccomp.a$/;" m
+LIB_STATIC src/python/Makefile /^LIB_STATIC = ..\/libseccomp.a$/;" m
+LINK_EXEC macros.mk /^ LINK_EXEC = @echo " LD $@";$/;" m
+LINK_LIB macros.mk /^ LINK_LIB = @echo " LD $@" \\$/;" m
+LN macros.mk /^LN ?= ln$/;" m
+LT src/python/seccomp.pyx /^LT = libseccomp.SCMP_CMP_LT$/;" v
+MAKEDEP macros.mk /^MAKEDEP = @$(GCC) $(CPPFLAGS) -MM -MF $(patsubst %.o,%.d,$@) $<;$/;" m
+MAKEDEP_EXEC macros.mk /^MAKEDEP_EXEC = \\$/;" m
+MAN1 doc/Makefile /^MAN1 = \\$/;" m
+MAN3 doc/Makefile /^MAN3 = \\$/;" m
+MASKED_EQ src/python/seccomp.pyx /^MASKED_EQ = libseccomp.SCMP_CMP_MASKED_EQ$/;" v
+MKDIR macros.mk /^MKDIR ?= mkdir$/;" m
+MV macros.mk /^MV ?= mv$/;" m
+NATIVE src/python/seccomp.pyx /^ NATIVE = libseccomp.SCMP_ARCH_NATIVE$/;" v class:Arch
+NE src/python/seccomp.pyx /^NE = libseccomp.SCMP_CMP_NE$/;" v
+OBJS src/Makefile /^OBJS = \\$/;" m
+OBJS tests/Makefile /^OBJS = util.o$/;" m
+PR_GET_NO_NEW_PRIVS src/system.h 89;" d
+PR_SET_NO_NEW_PRIVS src/system.h 85;" d
+PYTHON macros.mk /^PYTHON ?= \/usr\/bin\/env python$/;" m
+PY_BUILD macros.mk /^ PY_BUILD = @echo " PYTHON build";$/;" m
+PY_DISTUTILS macros.mk /^PY_DISTUTILS = \\$/;" m
+PY_INSTALL macros.mk /^ PY_INSTALL = @echo " PYTHON install";$/;" m
+SECCOMP_MODE_DISABLED src/system.h 41;" d
+SECCOMP_MODE_FILTER src/system.h 43;" d
+SECCOMP_MODE_STRICT src/system.h 42;" d
+SECCOMP_RET_ACTION src/system.h 60;" d
+SECCOMP_RET_ACTION tools/bpf.h 59;" d
+SECCOMP_RET_ALLOW src/system.h 57;" d
+SECCOMP_RET_ALLOW tools/bpf.h 67;" d
+SECCOMP_RET_DATA src/system.h 61;" d
+SECCOMP_RET_DATA tools/bpf.h 60;" d
+SECCOMP_RET_ERRNO src/system.h 55;" d
+SECCOMP_RET_ERRNO tools/bpf.h 65;" d
+SECCOMP_RET_KILL src/system.h 53;" d
+SECCOMP_RET_KILL tools/bpf.h 63;" d
+SECCOMP_RET_TRACE src/system.h 56;" d
+SECCOMP_RET_TRACE tools/bpf.h 66;" d
+SECCOMP_RET_TRAP src/system.h 54;" d
+SECCOMP_RET_TRAP tools/bpf.h 64;" d
+SED macros.mk /^SED ?= sed$/;" m
+SHELL macros.mk /^SHELL = \/bin\/bash$/;" m
+SUBDIRS_BUILD Makefile /^SUBDIRS_BUILD = include src tests tools$/;" m
+SUBDIRS_INSTALL Makefile /^SUBDIRS_INSTALL = include src tools doc$/;" m
+SyscallFilter src/python/seccomp.pyx /^cdef class SyscallFilter:$/;" c
+TAR macros.mk /^TAR ?= tar$/;" m
+TESTS tests/Makefile /^TESTS = 01-sim-allow \\$/;" m
+TEST_PRIVATE tests/Makefile /^TEST_PRIVATE = 00-test$/;" m
+TGT_IMM src/gen_bpf.c /^ TGT_IMM, \/* resolved immediate value *\/$/;" e enum:bpf_jump_type file:
+TGT_K src/gen_bpf.c /^ TGT_K, \/* immediate "k" value *\/$/;" e enum:bpf_jump_type file:
+TGT_NONE src/gen_bpf.c /^ TGT_NONE = 0,$/;" e enum:bpf_jump_type file:
+TGT_NXT src/gen_bpf.c /^ TGT_NXT, \/* fall through to the next block *\/$/;" e enum:bpf_jump_type file:
+TGT_PTR_BLK src/gen_bpf.c /^ TGT_PTR_BLK, \/* pointer to an instruction block *\/$/;" e enum:bpf_jump_type file:
+TGT_PTR_DB src/gen_bpf.c /^ TGT_PTR_DB, \/* pointer to part of the filter db *\/$/;" e enum:bpf_jump_type file:
+TGT_PTR_HSH src/gen_bpf.c /^ TGT_PTR_HSH, \/* pointer to a block hash table *\/$/;" e enum:bpf_jump_type file:
+TOOLS tools/Makefile /^TOOLS = scmp_bpf_disasm \\$/;" m
+TOOLS_INSTALL tools/Makefile /^TOOLS_INSTALL = scmp_sys_resolver$/;" m
+TOPDIR macros.mk /^TOPDIR := $(shell \\$/;" m
+TRACE src/python/seccomp.pyx /^def TRACE(int value):$/;" f
+TRAP src/python/seccomp.pyx /^TRAP = libseccomp.SCMP_ACT_TRAP$/;" v
+V macros.mk /^V ?= 0$/;" m
+VERSION_HDR macros.mk /^VERSION_HDR = version.h$/;" m
+VERSION_MAJOR version.h 5;" d
+VERSION_MAJOR version_info.mk /^VERSION_MAJOR=0$/;" m
+VERSION_MICRO version.h 7;" d
+VERSION_MICRO version_info.mk /^VERSION_MICRO=0$/;" m
+VERSION_MINOR version.h 6;" d
+VERSION_MINOR version_info.mk /^VERSION_MINOR=0$/;" m
+VERSION_RELEASE version.h 4;" d
+VERSION_RELEASE version_info.mk /^VERSION_RELEASE=0.0.0$/;" m
+X32 src/python/seccomp.pyx /^ X32 = libseccomp.SCMP_ARCH_X32$/;" v class:Arch
+X32_SYSCALL_BIT src/arch-x32.h 30;" d
+X86 src/python/seccomp.pyx /^ X86 = libseccomp.SCMP_ARCH_X86$/;" v class:Arch
+X86_64 src/python/seccomp.pyx /^ X86_64 = libseccomp.SCMP_ARCH_X86_64$/;" v class:Arch
+_ARCH_ARM_H src/arch-arm.h 23;" d
+_ARCH_H src/arch.h 23;" d
+_ARCH_X32_H src/arch-x32.h 23;" d
+_ARCH_X86_H src/arch-x86.h 23;" d
+_ARCH_x86_64_H src/arch-x86_64.h 23;" d
+_BLK_MSZE src/gen_bpf.c 117;" d file:
+_BPF_H tools/bpf.h 23;" d
+_BPF_HASH_BITS src/gen_bpf.c 126;" d file:
+_BPF_HASH_MASK src/gen_bpf.c 128;" d file:
+_BPF_HASH_SIZE src/gen_bpf.c 127;" d file:
+_BPF_INSTR src/gen_bpf.c 156;" d file:
+_BPF_JMP_BLK src/gen_bpf.c 76;" d file:
+_BPF_JMP_DB src/gen_bpf.c 74;" d file:
+_BPF_JMP_HSH src/gen_bpf.c 78;" d file:
+_BPF_JMP_IMM src/gen_bpf.c 72;" d file:
+_BPF_JMP_MAX src/gen_bpf.c 82;" d file:
+_BPF_JMP_MAX_RET src/gen_bpf.c 83;" d file:
+_BPF_JMP_NO src/gen_bpf.c 68;" d file:
+_BPF_JMP_NXT src/gen_bpf.c 70;" d file:
+_BPF_K src/gen_bpf.c 80;" d file:
+_BPF_OFFSET_SYSCALL src/gen_bpf.c 91;" d file:
+_BPF_SYSCALL src/gen_bpf.c 92;" d file:
+_CONFIGURE_H configure.h 5;" d
+_DB_PRI_MASK_CHAIN src/db.c 41;" d file:
+_DB_PRI_MASK_USER src/db.c 42;" d file:
+_DB_PRI_USER src/db.c 43;" d file:
+_DB_STA_FREED src/db.c 36;" d file:
+_DB_STA_VALID src/db.c 35;" d file:
+_FILTER_DB_H src/db.h 23;" d
+_HASH_H src/hash.h 19;" d
+_OP_FMT tools/scmp_bpf_disasm.c 35;" d file:
+_SYSTEM_H src/system.h 23;" d
+_TRANSLATOR_BPF_H src/gen_bpf.h 23;" d
+_TRANSLATOR_STR_H src/gen_pfc.h 23;" d
+_UTIL_TEST_H tests/util.h 23;" d
+_VERSION_H version.h 3;" d
+__NR_OABI_SYSCALL_BASE src/arch-arm-syscalls.c 29;" d file:
+__NR_SYSCALL_BASE src/arch-arm-syscalls.c 34;" d file:
+__NR_SYSCALL_BASE src/arch-arm-syscalls.c 36;" d file:
+__author__ src/python/seccomp.pyx /^__author__ = 'Paul Moore <paul@paul-moore.com>'$/;" v
+__blk_free src/gen_bpf.c /^static void __blk_free(struct bpf_state *state, struct bpf_blk *blk)$/;" f file:
+__cinit__ src/python/seccomp.pyx /^ def __cinit__(self, arg, op, datum_a, datum_b = 0):$/;" m class:Arg file:
+__cinit__ src/python/seccomp.pyx /^ def __cinit__(self, int defaction):$/;" m class:SyscallFilter file:
+__date__ src/python/seccomp.pyx /^__date__ = "7 January 2013"$/;" v
+__db_tree_free src/db.c /^static unsigned int __db_tree_free(struct db_arg_chain_tree *tree)$/;" f file:
+__dealloc__ src/python/seccomp.pyx /^ def __dealloc__(self):$/;" m class:SyscallFilter file:
+__x86_NR_ipc src/arch-x86.c 31;" d file:
+__x86_NR_socketcall src/arch-x86.c 30;" d file:
+_blk_append src/gen_bpf.c /^static struct bpf_blk *_blk_append(struct bpf_state *state,$/;" f file:
+_blk_free src/gen_bpf.c /^static void _blk_free(struct bpf_state *state, struct bpf_blk *blk)$/;" f file:
+_bpf_append_blk src/gen_bpf.c /^static int _bpf_append_blk(struct bpf_program *prg, const struct bpf_blk *blk)$/;" f file:
+_ctx_valid src/api.c /^static int _ctx_valid(const scmp_filter_ctx *ctx)$/;" f file:
+_db_node_mask_fixup src/db.c /^static void _db_node_mask_fixup(struct db_arg_chain_tree *node)$/;" f file:
+_db_rule_gen_32 src/db.c /^static struct db_sys_list *_db_rule_gen_32(const struct arch_def *arch,$/;" f file:
+_db_rule_gen_64 src/db.c /^static struct db_sys_list *_db_rule_gen_64(const struct arch_def *arch,$/;" f file:
+_db_tree_act_check src/db.c /^static int _db_tree_act_check(struct db_arg_chain_tree *tree, uint32_t action)$/;" f file:
+_db_tree_free src/db.c /^static unsigned int _db_tree_free(struct db_arg_chain_tree *tree)$/;" f file:
+_db_tree_remove src/db.c /^static unsigned int _db_tree_remove(struct db_arg_chain_tree **tree,$/;" f file:
+_db_tree_sub_prune src/db.c /^static int _db_tree_sub_prune(struct db_arg_chain_tree **tree_head,$/;" f file:
+_gen_bpf_action src/gen_bpf.c /^static struct bpf_blk *_gen_bpf_action(struct bpf_state *state,$/;" f file:
+_gen_bpf_action_hsh src/gen_bpf.c /^static struct bpf_blk *_gen_bpf_action_hsh(struct bpf_state *state,$/;" f file:
+_gen_bpf_arch src/gen_bpf.c /^static struct bpf_blk *_gen_bpf_arch(struct bpf_state *state,$/;" f file:
+_gen_bpf_build_bpf src/gen_bpf.c /^static int _gen_bpf_build_bpf(struct bpf_state *state,$/;" f file:
+_gen_bpf_build_jmp src/gen_bpf.c /^static int _gen_bpf_build_jmp(struct bpf_state *state,$/;" f file:
+_gen_bpf_build_jmp_ret src/gen_bpf.c /^static int _gen_bpf_build_jmp_ret(struct bpf_state *state,$/;" f file:
+_gen_bpf_chain src/gen_bpf.c /^static struct bpf_blk *_gen_bpf_chain(struct bpf_state *state,$/;" f file:
+_gen_bpf_chain_lvl_res src/gen_bpf.c /^static struct bpf_blk *_gen_bpf_chain_lvl_res(struct bpf_state *state,$/;" f file:
+_gen_bpf_find_nxt src/gen_bpf.c /^static struct bpf_blk *_gen_bpf_find_nxt(const struct bpf_blk *blk,$/;" f file:
+_gen_bpf_node src/gen_bpf.c /^static struct bpf_blk *_gen_bpf_node(struct bpf_state *state,$/;" f file:
+_gen_bpf_syscall src/gen_bpf.c /^static struct bpf_blk *_gen_bpf_syscall(struct bpf_state *state,$/;" f file:
+_gen_pfc_arch src/gen_pfc.c /^static int _gen_pfc_arch(const struct db_filter_col *col,$/;" f file:
+_gen_pfc_chain src/gen_pfc.c /^static void _gen_pfc_chain(const struct arch_def *arch,$/;" f file:
+_gen_pfc_syscall src/gen_pfc.c /^static void _gen_pfc_syscall(const struct arch_def *arch,$/;" f file:
+_hsh_add src/gen_bpf.c /^static int _hsh_add(struct bpf_state *state, struct bpf_blk **blk_p,$/;" f file:
+_hsh_find src/gen_bpf.c /^static struct bpf_blk *_hsh_find(const struct bpf_state *state, uint64_t h_val)$/;" f file:
+_hsh_find_bkt src/gen_bpf.c /^static struct bpf_hash_bkt *_hsh_find_bkt(const struct bpf_state *state,$/;" f file:
+_hsh_find_once src/gen_bpf.c /^static struct bpf_blk *_hsh_find_once(const struct bpf_state *state,$/;" f file:
+_hsh_remove src/gen_bpf.c /^static struct bpf_blk *_hsh_remove(struct bpf_state *state, uint64_t h_val)$/;" f file:
+_indent src/gen_pfc.c /^static void _indent(FILE *fds, unsigned int lvl)$/;" f file:
+_pfc_action src/gen_pfc.c /^static void _pfc_action(FILE *fds, uint32_t action)$/;" f file:
+_pfc_arch src/gen_pfc.c /^static const char *_pfc_arch(const struct arch_def *arch)$/;" f file:
+_pfc_arg src/gen_pfc.c /^static void _pfc_arg(FILE *fds,$/;" f file:
+_program_free src/gen_bpf.c /^static void _program_free(struct bpf_program *prg)$/;" f file:
+_seccomp_rule_add src/api.c /^static int _seccomp_rule_add(struct db_filter_col *col,$/;" f file:
+_state_release src/gen_bpf.c /^static void _state_release(struct bpf_state *state)$/;" f file:
+_syscall_valid src/api.c /^static int _syscall_valid(int syscall)$/;" f file:
+_trap_handler tests/util.c /^static void _trap_handler(int signal, siginfo_t *info, void *ctx)$/;" f file:
+acc tools/scmp_bpf_sim.c /^ uint32_t acc;$/;" m struct:sim_state file:
+acc_state src/gen_bpf.c /^ struct acc_state acc_state;$/;" m struct:bpf_blk typeref:struct:bpf_blk::acc_state file:
+acc_state src/gen_bpf.c /^struct acc_state {$/;" s file:
+act_badarch src/db.h /^ uint32_t act_badarch;$/;" m struct:db_filter_attr
+act_default src/db.h /^ uint32_t act_default;$/;" m struct:db_filter_attr
+act_f src/db.h /^ uint32_t act_f;$/;" m struct:db_arg_chain_tree
+act_f_flg src/db.h /^ bool act_f_flg;$/;" m struct:db_arg_chain_tree
+act_t src/db.h /^ uint32_t act_t;$/;" m struct:db_arg_chain_tree
+act_t_flg src/db.h /^ bool act_t_flg;$/;" m struct:db_arg_chain_tree
+action src/db.h /^ uint32_t action;$/;" m struct:db_sys_list
+add_arch src/python/seccomp.pyx /^ def add_arch(self, arch):$/;" m class:SyscallFilter
+add_rule src/python/seccomp.pyx /^ def add_rule(self, int action, syscall, *args):$/;" m class:SyscallFilter
+add_rule_exactly src/python/seccomp.pyx /^ def add_rule_exactly(self, int action, syscall, *args):$/;" m class:SyscallFilter
+arch src/db.h /^ const struct arch_def *arch;$/;" m struct:db_filter typeref:struct:db_filter::arch_def
+arch src/gen_bpf.c /^ const struct arch_def *arch;$/;" m struct:bpf_state typeref:struct:bpf_state::arch_def file:
+arch src/system.h /^ __u32 arch;$/;" m struct:seccomp_data
+arch tools/bpf.h /^ uint32_t arch;$/;" m struct:seccomp_data
+arch_arg_count_max src/arch.c /^int arch_arg_count_max(const struct arch_def *arch)$/;" f
+arch_arg_offset src/arch.h 91;" d
+arch_arg_offset_hi src/arch.c /^int arch_arg_offset_hi(const struct arch_def *arch, unsigned int arg)$/;" f
+arch_arg_offset_lo src/arch.c /^int arch_arg_offset_lo(const struct arch_def *arch, unsigned int arg)$/;" f
+arch_def src/arch.h /^struct arch_def {$/;" s
+arch_def_arm src/arch-arm.c /^const struct arch_def arch_def_arm = {$/;" v typeref:struct:arch_def
+arch_def_lookup src/arch.c /^const struct arch_def *arch_def_lookup(uint32_t token)$/;" f
+arch_def_native src/arch.c /^const struct arch_def *arch_def_native = &arch_def_arm;$/;" v typeref:struct:arch_def
+arch_def_native src/arch.c /^const struct arch_def *arch_def_native = &arch_def_x32;$/;" v typeref:struct:arch_def
+arch_def_native src/arch.c /^const struct arch_def *arch_def_native = &arch_def_x86;$/;" v typeref:struct:arch_def
+arch_def_native src/arch.c /^const struct arch_def *arch_def_native = &arch_def_x86_64;$/;" v typeref:struct:arch_def
+arch_def_x32 src/arch-x32.c /^const struct arch_def arch_def_x32 = {$/;" v typeref:struct:arch_def
+arch_def_x86 src/arch-x86.c /^const struct arch_def arch_def_x86 = {$/;" v typeref:struct:arch_def
+arch_def_x86_64 src/arch-x86_64.c /^const struct arch_def arch_def_x86_64 = {$/;" v typeref:struct:arch_def
+arch_filter_rewrite src/arch.c /^int arch_filter_rewrite(const struct arch_def *arch,$/;" f
+arch_syscall_def src/arch.h /^struct arch_syscall_def {$/;" s
+arch_syscall_resolve_name src/arch.c /^int arch_syscall_resolve_name(const struct arch_def *arch, const char *name)$/;" f
+arch_syscall_resolve_num src/arch.c /^const char *arch_syscall_resolve_num(const struct arch_def *arch, int num)$/;" f
+arch_syscall_rewrite src/arch.c /^int arch_syscall_rewrite(const struct arch_def *arch, bool strict, int *syscall)$/;" f
+arch_syscall_translate src/arch.c /^int arch_syscall_translate(const struct arch_def *arch, int *syscall)$/;" f
+arch_valid src/arch.c /^int arch_valid(uint32_t arch)$/;" f
+arg src/db.h /^ unsigned int arg;$/;" m struct:db_api_arg
+arg src/db.h /^ unsigned int arg;$/;" m struct:db_arg_chain_tree
+arg_offset src/db.h /^ unsigned int arg_offset;$/;" m struct:db_arg_chain_tree
+argparse tests/01-sim-allow.py /^import argparse$/;" i
+argparse tests/02-sim-basic.py /^import argparse$/;" i
+argparse tests/03-sim-basic_chains.py /^import argparse$/;" i
+argparse tests/04-sim-multilevel_chains.py /^import argparse$/;" i
+argparse tests/05-sim-long_jumps.py /^import argparse$/;" i
+argparse tests/06-sim-actions.py /^import argparse$/;" i
+argparse tests/07-sim-db_bug_looping.py /^import argparse$/;" i
+argparse tests/08-sim-subtree_checks.py /^import argparse$/;" i
+argparse tests/09-sim-syscall_priority_pre.py /^import argparse$/;" i
+argparse tests/10-sim-syscall_priority_post.py /^import argparse$/;" i
+argparse tests/11-basic-basic_errors.py /^import argparse$/;" i
+argparse tests/12-sim-basic_masked_ops.py /^import argparse$/;" i
+argparse tests/13-basic-attrs.py /^import argparse$/;" i
+argparse tests/14-sim-reset.py /^import argparse$/;" i
+argparse tests/15-basic-resolver.py /^import argparse$/;" i
+argparse tests/16-sim-arch_basic.py /^import argparse$/;" i
+argparse tests/17-sim-arch_merge.py /^import argparse$/;" i
+argparse tests/18-sim-basic_whitelist.py /^import argparse$/;" i
+argparse tests/19-sim-missing_syscalls.py /^import argparse$/;" i
+argparse tests/20-live-basic_die.py /^import argparse$/;" i
+argparse tests/21-live-basic_allow.py /^import argparse$/;" i
+argparse tests/22-sim-basic_chains_array.py /^import argparse$/;" i
+argparse tests/23-sim-arch_all_basic.py /^import argparse$/;" i
+argparse tests/24-live-arg_allow.py /^import argparse$/;" i
+argparse tests/25-sim-multilevel_chains_adv.py /^import argparse$/;" i
+argparse tests/util.py /^import argparse$/;" i
+args src/system.h /^ __u64 args[6];$/;" m struct:seccomp_data
+args tests/01-sim-allow.py /^args = util.get_opt()$/;" v
+args tests/02-sim-basic.py /^args = util.get_opt()$/;" v
+args tests/03-sim-basic_chains.py /^args = util.get_opt()$/;" v
+args tests/04-sim-multilevel_chains.py /^args = util.get_opt()$/;" v
+args tests/05-sim-long_jumps.py /^args = util.get_opt()$/;" v
+args tests/06-sim-actions.py /^args = util.get_opt()$/;" v
+args tests/07-sim-db_bug_looping.py /^args = util.get_opt()$/;" v
+args tests/08-sim-subtree_checks.py /^args = util.get_opt()$/;" v
+args tests/09-sim-syscall_priority_pre.py /^args = util.get_opt()$/;" v
+args tests/10-sim-syscall_priority_post.py /^args = util.get_opt()$/;" v
+args tests/12-sim-basic_masked_ops.py /^args = util.get_opt()$/;" v
+args tests/14-sim-reset.py /^args = util.get_opt()$/;" v
+args tests/16-sim-arch_basic.py /^args = util.get_opt()$/;" v
+args tests/17-sim-arch_merge.py /^args = util.get_opt()$/;" v
+args tests/18-sim-basic_whitelist.py /^args = util.get_opt()$/;" v
+args tests/19-sim-missing_syscalls.py /^args = util.get_opt()$/;" v
+args tests/22-sim-basic_chains_array.py /^args = util.get_opt()$/;" v
+args tests/23-sim-arch_all_basic.py /^args = util.get_opt()$/;" v
+args tests/25-sim-multilevel_chains_adv.py /^args = util.get_opt()$/;" v
+args tools/bpf.h /^ uint64_t args[BPF_SYS_ARG_MAX];$/;" m struct:seccomp_data
+arm_arg_count_max src/arch-arm.h 30;" d
+arm_syscall_resolve_name src/arch-arm-syscalls.c /^int arm_syscall_resolve_name(const char *name)$/;" f
+arm_syscall_resolve_num src/arch-arm-syscalls.c /^const char *arm_syscall_resolve_num(int num)$/;" f
+arm_syscall_table src/arch-arm-syscalls.c /^const struct arch_syscall_def arm_syscall_table[] = \\$/;" v typeref:struct:arch_syscall_def
+attr src/db.h /^ struct db_filter_attr attr;$/;" m struct:db_filter_col typeref:struct:db_filter_col::db_filter_attr
+attr src/gen_bpf.c /^ const struct db_filter_attr *attr;$/;" m struct:bpf_state typeref:struct:bpf_state::db_filter_attr file:
+blk src/gen_bpf.c /^ struct bpf_blk *blk;$/;" m union:bpf_jump::__anon1 typeref:struct:bpf_jump::__anon1::bpf_blk file:
+blk src/gen_bpf.c /^ struct bpf_blk *blk;$/;" m struct:bpf_hash_bkt typeref:struct:bpf_hash_bkt::bpf_blk file:
+blk_alloc src/gen_bpf.c /^ unsigned int blk_alloc;$/;" m struct:bpf_blk file:
+blk_cnt src/gen_bpf.c /^ unsigned int blk_cnt;$/;" m struct:bpf_blk file:
+blk_cnt src/gen_bpf.h /^ uint16_t blk_cnt;$/;" m struct:bpf_program
+blks src/gen_bpf.c /^ struct bpf_instr *blks;$/;" m struct:bpf_blk typeref:struct:bpf_blk::bpf_instr file:
+blks src/gen_bpf.h /^ bpf_instr_raw *blks;$/;" m struct:bpf_program
+bpf src/gen_bpf.c /^ struct bpf_program *bpf;$/;" m struct:bpf_state typeref:struct:bpf_state::bpf_program file:
+bpf_blk src/gen_bpf.c /^struct bpf_blk {$/;" s file:
+bpf_decode tools/scmp_bpf_disasm.c /^static int bpf_decode(FILE *file)$/;" f file:
+bpf_decode_args tools/scmp_bpf_disasm.c /^static void bpf_decode_args(const bpf_instr_raw *bpf, unsigned int line)$/;" f file:
+bpf_decode_op tools/scmp_bpf_disasm.c /^static void bpf_decode_op(const bpf_instr_raw *bpf)$/;" f file:
+bpf_execute tools/scmp_bpf_sim.c /^static void bpf_execute(const struct bpf_program *prg,$/;" f file:
+bpf_flg tests/util.h /^ int bpf_flg;$/;" m struct:util_options
+bpf_hash_bkt src/gen_bpf.c /^struct bpf_hash_bkt {$/;" s file:
+bpf_instr src/gen_bpf.c /^struct bpf_instr {$/;" s file:
+bpf_instr_raw src/system.h /^typedef struct sock_filter bpf_instr_raw;$/;" t typeref:struct:sock_filter
+bpf_instr_raw tools/bpf.h /^typedef struct sock_filter bpf_instr_raw;$/;" t typeref:struct:sock_filter
+bpf_jump src/gen_bpf.c /^struct bpf_jump {$/;" s file:
+bpf_jump_type src/gen_bpf.c /^enum bpf_jump_type {$/;" g file:
+bpf_program src/gen_bpf.h /^struct bpf_program {$/;" s
+bpf_program tools/scmp_bpf_sim.c /^struct bpf_program {$/;" s file:
+bpf_state src/gen_bpf.c /^struct bpf_state {$/;" s file:
+build_ext src/python/setup.py /^from Cython.Distutils import build_ext$/;" i
+chains src/db.h /^ struct db_arg_chain_tree *chains;$/;" m struct:db_sys_list typeref:struct:db_sys_list::db_arg_chain_tree
+cmdclass src/python/setup.py /^ cmdclass = {'build_ext': build_ext},$/;" v
+cnf_entry configure /^function cnf_entry() {$/;" f
+cnf_footer configure /^function cnf_footer() {$/;" f
+cnf_h_entry configure /^function cnf_h_entry() {$/;" f
+cnf_h_footer configure /^function cnf_h_footer() {$/;" f
+cnf_h_header configure /^function cnf_h_header() {$/;" f
+cnf_header configure /^function cnf_header() {$/;" f
+cnf_mk_entry configure /^function cnf_mk_entry() {$/;" f
+cnf_mk_footer configure /^function cnf_mk_footer() {$/;" f
+cnf_mk_header configure /^function cnf_mk_header() {$/;" f
+cnf_reset configure /^function cnf_reset() {$/;" f
+code tools/bpf.h /^ uint16_t code;$/;" m struct:sock_filter
+ctx tests/01-sim-allow.py /^ctx = test(args)$/;" v
+ctx tests/02-sim-basic.py /^ctx = test(args)$/;" v
+ctx tests/03-sim-basic_chains.py /^ctx = test(args)$/;" v
+ctx tests/04-sim-multilevel_chains.py /^ctx = test(args)$/;" v
+ctx tests/05-sim-long_jumps.py /^ctx = test(args)$/;" v
+ctx tests/06-sim-actions.py /^ctx = test(args)$/;" v
+ctx tests/07-sim-db_bug_looping.py /^ctx = test(args)$/;" v
+ctx tests/08-sim-subtree_checks.py /^ctx = test(args)$/;" v
+ctx tests/09-sim-syscall_priority_pre.py /^ctx = test(args)$/;" v
+ctx tests/10-sim-syscall_priority_post.py /^ctx = test(args)$/;" v
+ctx tests/12-sim-basic_masked_ops.py /^ctx = test(args)$/;" v
+ctx tests/14-sim-reset.py /^ctx = test(args)$/;" v
+ctx tests/16-sim-arch_basic.py /^ctx = test(args)$/;" v
+ctx tests/17-sim-arch_merge.py /^ctx = test(args)$/;" v
+ctx tests/18-sim-basic_whitelist.py /^ctx = test(args)$/;" v
+ctx tests/19-sim-missing_syscalls.py /^ctx = test(args)$/;" v
+ctx tests/22-sim-basic_chains_array.py /^ctx = test(args)$/;" v
+ctx tests/23-sim-arch_all_basic.py /^ctx = test(args)$/;" v
+ctx tests/25-sim-multilevel_chains_adv.py /^ctx = test(args)$/;" v
+datum src/db.h /^ scmp_datum_t datum;$/;" m struct:db_api_arg
+datum src/db.h /^ uint32_t datum;$/;" m struct:db_arg_chain_tree
+db src/gen_bpf.c /^ struct db_arg_chain_tree *db;$/;" m union:bpf_jump::__anon1 typeref:struct:bpf_jump::__anon1::db_arg_chain_tree file:
+db_action_valid src/db.c /^int db_action_valid(uint32_t action)$/;" f
+db_api_arg src/db.h /^struct db_api_arg {$/;" s
+db_arg_chain_tree src/db.h /^struct db_arg_chain_tree {$/;" s
+db_chain_eq src/db.h 75;" d
+db_chain_eq_result src/db.h 85;" d
+db_chain_gt src/db.h 79;" d
+db_chain_leaf src/db.h 83;" d
+db_chain_lt src/db.h 71;" d
+db_col_arch_exist src/db.c /^int db_col_arch_exist(struct db_filter_col *col, uint32_t arch_token)$/;" f
+db_col_attr_get src/db.c /^int db_col_attr_get(const struct db_filter_col *col,$/;" f
+db_col_attr_set src/db.c /^int db_col_attr_set(struct db_filter_col *col,$/;" f
+db_col_db_add src/db.c /^int db_col_db_add(struct db_filter_col *col, struct db_filter *db)$/;" f
+db_col_db_remove src/db.c /^int db_col_db_remove(struct db_filter_col *col, uint32_t arch_token)$/;" f
+db_col_init src/db.c /^struct db_filter_col *db_col_init(uint32_t def_action)$/;" f
+db_col_merge src/db.c /^int db_col_merge(struct db_filter_col *col_dst, struct db_filter_col *col_src)$/;" f
+db_col_release src/db.c /^void db_col_release(struct db_filter_col *col)$/;" f
+db_col_reset src/db.c /^void db_col_reset(struct db_filter_col *col, uint32_t def_action)$/;" f
+db_col_valid src/db.c /^int db_col_valid(struct db_filter_col *col)$/;" f
+db_filter src/db.h /^struct db_filter {$/;" s
+db_filter_attr src/db.h /^struct db_filter_attr {$/;" s
+db_filter_col src/db.h /^struct db_filter_col {$/;" s
+db_init src/db.c /^struct db_filter *db_init(const struct arch_def *arch)$/;" f
+db_list_foreach src/db.h 156;" d
+db_release src/db.c /^void db_release(struct db_filter *db)$/;" f
+db_reset src/db.c /^void db_reset(struct db_filter *db)$/;" f
+db_rule_add src/db.c /^int db_rule_add(struct db_filter *db, uint32_t action, unsigned int syscall,$/;" f
+db_sys_list src/db.h /^struct db_sys_list {$/;" s
+db_syscall_priority src/db.c /^int db_syscall_priority(struct db_filter *db,$/;" f
+def_hsh src/gen_bpf.c /^ uint64_t def_hsh;$/;" m struct:bpf_state file:
+description src/python/setup.py /^ description = "Python binding for libseccomp",$/;" v
+end_action tools/scmp_bpf_sim.c /^static void end_action(uint32_t action, unsigned int line)$/;" f file:
+endian src/arch.h /^ } endian;$/;" m struct:arch_def typeref:enum:arch_def::__anon3
+errno src/python/seccomp.pyx /^import errno$/;" i
+errno tests/06-sim-actions.py /^import errno$/;" i
+exist_arch src/python/seccomp.pyx /^ def exist_arch(self, arch):$/;" m class:SyscallFilter
+exit_error tools/scmp_bpf_sim.c /^static void exit_error(unsigned int rc, unsigned int line)$/;" f file:
+exit_fault tools/scmp_bpf_sim.c /^static void exit_fault(unsigned int rc)$/;" f file:
+exit_usage tools/scmp_arch_detect.c /^static void exit_usage(const char *program)$/;" f file:
+exit_usage tools/scmp_bpf_sim.c /^static void exit_usage(const char *program)$/;" f file:
+exit_usage tools/scmp_sys_resolver.c /^static void exit_usage(const char *program)$/;" f file:
+export_bpf src/python/seccomp.pyx /^ def export_bpf(self, file):$/;" m class:SyscallFilter
+export_pfc src/python/seccomp.pyx /^ def export_pfc(self, file):$/;" m class:SyscallFilter
+ext_modules src/python/setup.py /^ ext_modules = [$/;" v
+extra_objects src/python/setup.py /^ extra_objects=["..\/libseccomp.a"])$/;" v
+filter_cnt src/db.h /^ unsigned int filter_cnt;$/;" m struct:db_filter_col
+filter_output tests/util.py /^def filter_output(args, ctx):$/;" f
+filters src/db.h /^ struct db_filter **filters;$/;" m struct:db_filter_col typeref:struct:db_filter_col::db_filter
+final src/hash.c 149;" d file:
+flag_dup src/gen_bpf.c /^ bool flag_dup; \/* duplicate block and in use *\/$/;" m struct:bpf_blk file:
+flag_hash src/gen_bpf.c /^ bool flag_hash; \/* added to the hash table *\/$/;" m struct:bpf_blk file:
+flag_unique src/gen_bpf.c /^ bool flag_unique; \/* ->blks is unique to this block *\/$/;" m struct:bpf_blk file:
+found src/gen_bpf.c /^ unsigned int found;$/;" m struct:bpf_hash_bkt file:
+gen_bpf_generate src/gen_bpf.c /^struct bpf_program *gen_bpf_generate(const struct db_filter_col *col)$/;" f
+gen_bpf_release src/gen_bpf.c /^void gen_bpf_release(struct bpf_program *program)$/;" f
+gen_pfc_generate src/gen_pfc.c /^int gen_pfc_generate(const struct db_filter_col *col, int fd)$/;" f
+generate_random_data tests/regression /^function generate_random_data() {$/;" f
+generate_test_num tests/regression /^function generate_test_num() {$/;" f
+get_attr src/python/seccomp.pyx /^ def get_attr(self, attr):$/;" m class:SyscallFilter
+get_opt tests/util.py /^def get_opt():$/;" f
+get_range tests/regression /^function get_range() {$/;" f
+hash src/gen_bpf.c /^ uint64_t hash;$/;" m union:bpf_jump::__anon1 file:
+hash src/gen_bpf.c /^ uint64_t hash;$/;" m struct:bpf_blk file:
+hash_nxt src/gen_bpf.c /^ struct bpf_blk *hash_nxt;$/;" m struct:bpf_blk typeref:struct:bpf_blk::bpf_blk file:
+hashbig src/hash.c /^uint32_t hashbig( const void *key, size_t length, uint32_t initval)$/;" f
+hashlittle src/hash.c /^uint32_t hashlittle( const void *key, size_t length, uint32_t initval)$/;" f
+hashlittle src/hash.c 44;" d file:
+hashlittle2 src/hash.c /^void hashlittle2($/;" f
+hashmask src/hash.c 67;" d file:
+hashsize src/hash.c 66;" d file:
+hashword src/hash.c /^uint32_t hashword($/;" f
+hashword2 src/hash.c /^void hashword2 ($/;" f
+htbl src/gen_bpf.c /^ struct bpf_hash_bkt *htbl[_BPF_HASH_SIZE];$/;" m struct:bpf_state typeref:struct:bpf_state::bpf_hash_bkt file:
+i tools/scmp_bpf_sim.c /^ bpf_instr_raw *i;$/;" m struct:bpf_program file:
+i_cnt tools/scmp_bpf_sim.c /^ size_t i_cnt;$/;" m struct:bpf_program file:
+imm_j src/gen_bpf.c /^ uint8_t imm_j;$/;" m union:bpf_jump::__anon1 file:
+imm_k src/gen_bpf.c /^ uint32_t imm_k;$/;" m union:bpf_jump::__anon1 file:
+install_trap tests/util.py /^def install_trap():$/;" f
+instruction_pointer src/system.h /^ __u64 instruction_pointer;$/;" m struct:seccomp_data
+instruction_pointer tools/bpf.h /^ uint64_t instruction_pointer;$/;" m struct:seccomp_data
+jf src/gen_bpf.c /^ struct bpf_jump jf;$/;" m struct:bpf_instr typeref:struct:bpf_instr::bpf_jump file:
+jf tools/bpf.h /^ uint8_t jf;$/;" m struct:sock_filter
+jt src/gen_bpf.c /^ struct bpf_jump jt;$/;" m struct:bpf_instr typeref:struct:bpf_instr::bpf_jump file:
+jt tools/bpf.h /^ uint8_t jt;$/;" m struct:sock_filter
+k src/gen_bpf.c /^ struct bpf_jump k;$/;" m struct:bpf_instr typeref:struct:bpf_instr::bpf_jump file:
+k tools/bpf.h /^ uint32_t k;$/;" m struct:sock_filter
+libseccomp src/python/seccomp.pyx /^cimport libseccomp$/;" i
+license src/python/setup.py /^ license = "LGPLv2.1",$/;" v
+load src/python/seccomp.pyx /^ def load(self):$/;" m class:SyscallFilter
+long_description src/python/setup.py /^ long_description = "Python API for the Linux Kernel's syscall filtering capability, seccomp.",$/;" v
+lvl_nxt src/db.h /^ struct db_arg_chain_tree *lvl_prv, *lvl_nxt;$/;" m struct:db_arg_chain_tree typeref:struct:db_arg_chain_tree::
+lvl_nxt src/gen_bpf.c /^ struct bpf_blk *lvl_prv, *lvl_nxt;$/;" m struct:bpf_blk typeref:struct:bpf_blk:: file:
+lvl_prv src/db.h /^ struct db_arg_chain_tree *lvl_prv, *lvl_nxt;$/;" m struct:db_arg_chain_tree typeref:struct:db_arg_chain_tree::db_arg_chain_tree
+lvl_prv src/gen_bpf.c /^ struct bpf_blk *lvl_prv, *lvl_nxt;$/;" m struct:bpf_blk typeref:struct:bpf_blk::bpf_blk file:
+main tests/00-test.c /^int main(void)$/;" f
+main tests/01-sim-allow.c /^int main(int argc, char *argv[])$/;" f
+main tests/02-sim-basic.c /^int main(int argc, char *argv[])$/;" f
+main tests/03-sim-basic_chains.c /^int main(int argc, char *argv[])$/;" f
+main tests/04-sim-multilevel_chains.c /^int main(int argc, char *argv[])$/;" f
+main tests/05-sim-long_jumps.c /^int main(int argc, char *argv[])$/;" f
+main tests/06-sim-actions.c /^int main(int argc, char *argv[])$/;" f
+main tests/07-sim-db_bug_looping.c /^int main(int argc, char *argv[])$/;" f
+main tests/08-sim-subtree_checks.c /^int main(int argc, char *argv[])$/;" f
+main tests/09-sim-syscall_priority_pre.c /^int main(int argc, char *argv[])$/;" f
+main tests/10-sim-syscall_priority_post.c /^int main(int argc, char *argv[])$/;" f
+main tests/11-basic-basic_errors.c /^int main(int argc, char *argv[])$/;" f
+main tests/12-sim-basic_masked_ops.c /^int main(int argc, char *argv[])$/;" f
+main tests/13-basic-attrs.c /^int main(int argc, char *argv[])$/;" f
+main tests/14-sim-reset.c /^int main(int argc, char *argv[])$/;" f
+main tests/15-basic-resolver.c /^int main(int argc, char *argv[])$/;" f
+main tests/16-sim-arch_basic.c /^int main(int argc, char *argv[])$/;" f
+main tests/17-sim-arch_merge.c /^int main(int argc, char *argv[])$/;" f
+main tests/18-sim-basic_whitelist.c /^int main(int argc, char *argv[])$/;" f
+main tests/19-sim-missing_syscalls.c /^int main(int argc, char *argv[])$/;" f
+main tests/20-live-basic_die.c /^int main(int argc, char *argv[])$/;" f
+main tests/21-live-basic_allow.c /^int main(int argc, char *argv[])$/;" f
+main tests/22-sim-basic_chains_array.c /^int main(int argc, char *argv[])$/;" f
+main tests/23-sim-arch_all_basic.c /^int main(int argc, char *argv[])$/;" f
+main tests/24-live-arg_allow.c /^int main(int argc, char *argv[])$/;" f
+main tests/25-sim-multilevel_chains_adv.c /^int main(int argc, char *argv[])$/;" f
+main tools/scmp_arch_detect.c /^int main(int argc, char *argv[])$/;" f
+main tools/scmp_bpf_disasm.c /^int main(int argc, char *argv[])$/;" f
+main tools/scmp_bpf_sim.c /^int main(int argc, char *argv[])$/;" f
+main tools/scmp_sys_resolver.c /^int main(int argc, char *argv[])$/;" f
+maintainer src/python/setup.py /^ maintainer = "Paul Moore",$/;" v
+maintainer_email src/python/setup.py /^ maintainer_email = "paul@paul-moore.com",$/;" v
+mask src/db.h /^ scmp_datum_t mask;$/;" m struct:db_api_arg
+mask src/db.h /^ uint32_t mask;$/;" m struct:db_arg_chain_tree
+mask src/gen_bpf.c /^ uint32_t mask;$/;" m struct:acc_state file:
+merge src/python/seccomp.pyx /^ def merge(self, SyscallFilter filter):$/;" m class:SyscallFilter
+mix src/hash.c 114;" d file:
+msg_error configure /^function msg_error() {$/;" f
+msg_summary configure /^function msg_summary() {$/;" f
+msg_usage configure /^function msg_usage() {$/;" f
+name src/arch.h /^ const char *name;$/;" m struct:arch_syscall_def
+name src/python/setup.py /^ name = "seccomp",$/;" v
+next src/db.h /^ struct db_sys_list *next;$/;" m struct:db_sys_list typeref:struct:db_sys_list::db_sys_list
+next src/gen_bpf.c /^ struct bpf_blk *prev, *next;$/;" m struct:bpf_blk typeref:struct:bpf_blk:: file:
+next src/gen_bpf.c /^ struct bpf_hash_bkt *next;$/;" m struct:bpf_hash_bkt typeref:struct:bpf_hash_bkt::bpf_hash_bkt file:
+next src/gen_pfc.c /^ struct pfc_sys_list *next;$/;" m struct:pfc_sys_list typeref:struct:pfc_sys_list::pfc_sys_list file:
+nnp_enable src/db.h /^ uint32_t nnp_enable;$/;" m struct:db_filter_attr
+node src/gen_bpf.c /^ const struct db_arg_chain_tree *node;$/;" m struct:bpf_blk typeref:struct:bpf_blk::db_arg_chain_tree file:
+node_cnt src/db.h /^ unsigned int node_cnt;$/;" m struct:db_sys_list
+nr src/system.h /^ int nr;$/;" m struct:seccomp_data
+nr tools/bpf.h /^ int32_t nr;$/;" m struct:seccomp_data
+num src/arch.h /^ unsigned int num;$/;" m struct:arch_syscall_def
+num src/db.h /^ unsigned int num;$/;" m struct:db_sys_list
+nxt src/gen_bpf.c /^ unsigned int nxt;$/;" m union:bpf_jump::__anon1 file:
+nxt_f src/db.h /^ struct db_arg_chain_tree *nxt_f;$/;" m struct:db_arg_chain_tree typeref:struct:db_arg_chain_tree::db_arg_chain_tree
+nxt_t src/db.h /^ struct db_arg_chain_tree *nxt_t;$/;" m struct:db_arg_chain_tree typeref:struct:db_arg_chain_tree::db_arg_chain_tree
+offset src/gen_bpf.c /^ int32_t offset;$/;" m struct:acc_state file:
+op src/db.h /^ enum scmp_compare op;$/;" m struct:db_arg_chain_tree typeref:enum:db_arg_chain_tree::scmp_compare
+op src/db.h /^ unsigned int op;$/;" m struct:db_api_arg
+op src/gen_bpf.c /^ uint16_t op;$/;" m struct:bpf_instr file:
+opt_verbose tools/scmp_bpf_sim.c /^static unsigned int opt_verbose = 0;$/;" v file:
+os src/python/setup.py /^import os$/;" i
+os tests/24-live-arg_allow.py /^import os$/;" i
+os tests/util.py /^import os$/;" i
+parse_action tests/util.py /^def parse_action(action):$/;" f
+pfc_sys_list src/gen_pfc.c /^struct pfc_sys_list {$/;" s file:
+platforms src/python/setup.py /^ platforms = "Linux",$/;" v
+prev src/gen_bpf.c /^ struct bpf_blk *prev, *next;$/;" m struct:bpf_blk typeref:struct:bpf_blk::bpf_blk file:
+pri_nxt src/db.h /^ struct db_sys_list *pri_prv, *pri_nxt;$/;" m struct:db_sys_list typeref:struct:db_sys_list::
+pri_prv src/db.h /^ struct db_sys_list *pri_prv, *pri_nxt;$/;" m struct:db_sys_list typeref:struct:db_sys_list::db_sys_list
+print_data tests/regression /^function print_data() {$/;" f
+print_result tests/regression /^function print_result() {$/;" f
+print_valgrind tests/regression /^function print_valgrind() {$/;" f
+priority src/db.h /^ unsigned int priority;$/;" m struct:db_sys_list
+priority src/gen_bpf.c /^ unsigned int priority;$/;" m struct:bpf_blk file:
+refcnt src/db.h /^ unsigned int refcnt;$/;" m struct:db_arg_chain_tree
+remove_arch src/python/seccomp.pyx /^ def remove_arch(self, arch):$/;" m class:SyscallFilter
+reset src/python/seccomp.pyx /^ def reset(self, int defaction = -1):$/;" m class:SyscallFilter
+resolve_syscall src/python/seccomp.pyx /^def resolve_syscall(arch, syscall):$/;" f
+rot src/hash.c 68;" d file:
+run_test tests/regression /^function run_test() {$/;" f
+run_test_basic tests/regression /^function run_test_basic() {$/;" f
+run_test_bpf_sim tests/regression /^function run_test_bpf_sim() {$/;" f
+run_test_bpf_sim_fuzz tests/regression /^function run_test_bpf_sim_fuzz() {$/;" f
+run_test_command tests/regression /^function run_test_command() {$/;" f
+run_test_live tests/regression /^function run_test_live() {$/;" f
+run_tests tests/regression /^function run_tests() {$/;" f
+seccomp_arch_add src/api.c /^int seccomp_arch_add(scmp_filter_ctx ctx, uint32_t arch_token)$/;" f
+seccomp_arch_exist src/api.c /^int seccomp_arch_exist(const scmp_filter_ctx ctx, uint32_t arch_token)$/;" f
+seccomp_arch_native src/api.c /^uint32_t seccomp_arch_native(void)$/;" f
+seccomp_arch_remove src/api.c /^int seccomp_arch_remove(scmp_filter_ctx ctx, uint32_t arch_token)$/;" f
+seccomp_attr_get src/api.c /^int seccomp_attr_get(const scmp_filter_ctx ctx,$/;" f
+seccomp_attr_set src/api.c /^int seccomp_attr_set(scmp_filter_ctx ctx,$/;" f
+seccomp_data src/system.h /^struct seccomp_data {$/;" s
+seccomp_data tools/bpf.h /^struct seccomp_data {$/;" s
+seccomp_export_bpf src/api.c /^int seccomp_export_bpf(const scmp_filter_ctx ctx, int fd)$/;" f
+seccomp_export_pfc src/api.c /^int seccomp_export_pfc(const scmp_filter_ctx ctx, int fd)$/;" f
+seccomp_init src/api.c /^scmp_filter_ctx seccomp_init(uint32_t def_action)$/;" f
+seccomp_load src/api.c /^int seccomp_load(const scmp_filter_ctx ctx)$/;" f
+seccomp_merge src/api.c /^int seccomp_merge(scmp_filter_ctx ctx_dst, scmp_filter_ctx ctx_src)$/;" f
+seccomp_release src/api.c /^void seccomp_release(scmp_filter_ctx ctx)$/;" f
+seccomp_reset src/api.c /^int seccomp_reset(scmp_filter_ctx ctx, uint32_t def_action)$/;" f
+seccomp_rule_add src/api.c /^int seccomp_rule_add(scmp_filter_ctx ctx,$/;" f
+seccomp_rule_add_array src/api.c /^int seccomp_rule_add_array(scmp_filter_ctx ctx,$/;" f
+seccomp_rule_add_exact src/api.c /^int seccomp_rule_add_exact(scmp_filter_ctx ctx, uint32_t action,$/;" f
+seccomp_rule_add_exact_array src/api.c /^int seccomp_rule_add_exact_array(scmp_filter_ctx ctx,$/;" f
+seccomp_syscall_priority src/api.c /^int seccomp_syscall_priority(scmp_filter_ctx ctx, int syscall, uint8_t priority)$/;" f
+seccomp_syscall_resolve_name src/api.c /^int seccomp_syscall_resolve_name(const char *name)$/;" f
+seccomp_syscall_resolve_name_arch src/api.c /^int seccomp_syscall_resolve_name_arch(uint32_t arch_token, const char *name)$/;" f
+seccomp_syscall_resolve_num_arch src/api.c /^char *seccomp_syscall_resolve_num_arch(uint32_t arch_token, int num)$/;" f
+set_attr src/python/seccomp.pyx /^ def set_attr(self, attr, int value):$/;" m class:SyscallFilter
+setup src/python/setup.py /^from distutils.core import setup$/;" i
+signal tests/util.py /^import signal$/;" i
+sim_state tools/scmp_bpf_sim.c /^struct sim_state {$/;" s file:
+size src/arch.h /^ } size;$/;" m struct:arch_def typeref:enum:arch_def::__anon2
+sock_filter tools/bpf.h /^struct sock_filter {$/;" s
+state src/db.h /^ int state;$/;" m struct:db_filter_col
+sys src/gen_pfc.c /^ struct db_sys_list *sys;$/;" m struct:pfc_sys_list typeref:struct:pfc_sys_list::db_sys_list file:
+sys tests/01-sim-allow.py /^import sys$/;" i
+sys tests/02-sim-basic.py /^import sys$/;" i
+sys tests/03-sim-basic_chains.py /^import sys$/;" i
+sys tests/04-sim-multilevel_chains.py /^import sys$/;" i
+sys tests/05-sim-long_jumps.py /^import sys$/;" i
+sys tests/06-sim-actions.py /^import sys$/;" i
+sys tests/07-sim-db_bug_looping.py /^import sys$/;" i
+sys tests/08-sim-subtree_checks.py /^import sys$/;" i
+sys tests/09-sim-syscall_priority_pre.py /^import sys$/;" i
+sys tests/10-sim-syscall_priority_post.py /^import sys$/;" i
+sys tests/11-basic-basic_errors.py /^import sys$/;" i
+sys tests/12-sim-basic_masked_ops.py /^import sys$/;" i
+sys tests/13-basic-attrs.py /^import sys$/;" i
+sys tests/14-sim-reset.py /^import sys$/;" i
+sys tests/15-basic-resolver.py /^import sys$/;" i
+sys tests/16-sim-arch_basic.py /^import sys$/;" i
+sys tests/17-sim-arch_merge.py /^import sys$/;" i
+sys tests/18-sim-basic_whitelist.py /^import sys$/;" i
+sys tests/19-sim-missing_syscalls.py /^import sys$/;" i
+sys tests/20-live-basic_die.py /^import sys$/;" i
+sys tests/21-live-basic_allow.py /^import sys$/;" i
+sys tests/22-sim-basic_chains_array.py /^import sys$/;" i
+sys tests/23-sim-arch_all_basic.py /^import sys$/;" i
+sys tests/24-live-arg_allow.py /^import sys$/;" i
+sys tests/25-sim-multilevel_chains_adv.py /^import sys$/;" i
+sys tests/util.py /^import sys$/;" i
+syscall_priority src/python/seccomp.pyx /^ def syscall_priority(self, syscall, int priority):$/;" m class:SyscallFilter
+syscalls src/db.h /^ struct db_sys_list *syscalls;$/;" m struct:db_filter typeref:struct:db_filter::db_sys_list
+system_arch src/python/seccomp.pyx /^def system_arch():$/;" f
+temp tools/scmp_bpf_sim.c /^ uint32_t temp[BPF_SCRATCH_SIZE];$/;" m struct:sim_state file:
+test tests/01-sim-allow.py /^def test(args):$/;" f
+test tests/02-sim-basic.py /^def test(args):$/;" f
+test tests/03-sim-basic_chains.py /^def test(args):$/;" f
+test tests/04-sim-multilevel_chains.py /^def test(args):$/;" f
+test tests/05-sim-long_jumps.py /^def test(args):$/;" f
+test tests/06-sim-actions.py /^def test(args):$/;" f
+test tests/07-sim-db_bug_looping.py /^def test(args):$/;" f
+test tests/08-sim-subtree_checks.py /^def test(args):$/;" f
+test tests/09-sim-syscall_priority_pre.py /^def test(args):$/;" f
+test tests/10-sim-syscall_priority_post.py /^def test(args):$/;" f
+test tests/11-basic-basic_errors.py /^def test():$/;" f
+test tests/12-sim-basic_masked_ops.py /^def test(args):$/;" f
+test tests/13-basic-attrs.py /^def test():$/;" f
+test tests/14-sim-reset.py /^def test(args):$/;" f
+test tests/15-basic-resolver.py /^def test():$/;" f
+test tests/16-sim-arch_basic.py /^def test(args):$/;" f
+test tests/17-sim-arch_merge.py /^def test(args):$/;" f
+test tests/18-sim-basic_whitelist.py /^def test(args):$/;" f
+test tests/19-sim-missing_syscalls.py /^def test(args):$/;" f
+test tests/20-live-basic_die.py /^def test():$/;" f
+test tests/21-live-basic_allow.py /^def test():$/;" f
+test tests/22-sim-basic_chains_array.py /^def test(args):$/;" f
+test tests/23-sim-arch_all_basic.py /^def test(args):$/;" f
+test tests/24-live-arg_allow.py /^def test():$/;" f
+test tests/25-sim-multilevel_chains_adv.py /^def test(args):$/;" f
+test_deps configure /^function test_deps() {$/;" f
+tgt src/gen_bpf.c /^ } tgt;$/;" m struct:bpf_jump typeref:union:bpf_jump::__anon1 file:
+tmpl_filter configure /^function tmpl_filter() {$/;" f
+to_c src/python/seccomp.pyx /^ def to_c(self):$/;" m class:Arg
+token src/arch.h /^ uint32_t token;$/;" m struct:arch_def
+token_bpf src/arch.h /^ uint32_t token_bpf;$/;" m struct:arch_def
+trap_handler tests/util.py /^def trap_handler(signum, frame):$/;" f
+type src/gen_bpf.c /^ enum bpf_jump_type type;$/;" m struct:bpf_jump typeref:enum:bpf_jump::bpf_jump_type file:
+uint32_t src/python/libseccomp.pxd /^from libc.stdint cimport uint8_t, uint32_t, uint64_t$/;" i
+uint32_t src/python/seccomp.pyx /^from libc.stdint cimport uint32_t$/;" i
+uint64_t src/python/libseccomp.pxd /^from libc.stdint cimport uint8_t, uint32_t, uint64_t$/;" i
+uint8_t src/python/libseccomp.pxd /^from libc.stdint cimport uint8_t, uint32_t, uint64_t$/;" i
+url src/python/setup.py /^ url = "http:\/\/libseccomp.sf.net",$/;" v
+usage tests/regression /^function usage() {$/;" f
+util tests/01-sim-allow.py /^import util$/;" i
+util tests/02-sim-basic.py /^import util$/;" i
+util tests/03-sim-basic_chains.py /^import util$/;" i
+util tests/04-sim-multilevel_chains.py /^import util$/;" i
+util tests/05-sim-long_jumps.py /^import util$/;" i
+util tests/06-sim-actions.py /^import util$/;" i
+util tests/07-sim-db_bug_looping.py /^import util$/;" i
+util tests/08-sim-subtree_checks.py /^import util$/;" i
+util tests/09-sim-syscall_priority_pre.py /^import util$/;" i
+util tests/10-sim-syscall_priority_post.py /^import util$/;" i
+util tests/11-basic-basic_errors.py /^import util$/;" i
+util tests/12-sim-basic_masked_ops.py /^import util$/;" i
+util tests/13-basic-attrs.py /^import util$/;" i
+util tests/14-sim-reset.py /^import util$/;" i
+util tests/15-basic-resolver.py /^import util$/;" i
+util tests/16-sim-arch_basic.py /^import util$/;" i
+util tests/17-sim-arch_merge.py /^import util$/;" i
+util tests/18-sim-basic_whitelist.py /^import util$/;" i
+util tests/19-sim-missing_syscalls.py /^import util$/;" i
+util tests/20-live-basic_die.py /^import util$/;" i
+util tests/21-live-basic_allow.py /^import util$/;" i
+util tests/22-sim-basic_chains_array.py /^import util$/;" i
+util tests/23-sim-arch_all_basic.py /^import util$/;" i
+util tests/24-live-arg_allow.py /^import util$/;" i
+util tests/25-sim-multilevel_chains_adv.py /^import util$/;" i
+util_action_parse tests/util.c /^int util_action_parse(const char *action)$/;" f
+util_file_write tests/util.c /^int util_file_write(const char *path)$/;" f
+util_filter_output tests/util.c /^int util_filter_output(const struct util_options *opts,$/;" f
+util_getopt tests/util.c /^int util_getopt(int argc, char *argv[], struct util_options *opts)$/;" f
+util_options tests/util.h /^struct util_options {$/;" s
+util_trap_install tests/util.c /^int util_trap_install(void)$/;" f
+valid src/db.h /^ bool valid;$/;" m struct:db_api_arg
+valid src/db.h /^ bool valid;$/;" m struct:db_sys_list
+verify_deps configure /^function verify_deps() {$/;" f
+verify_deps tests/regression /^function verify_deps() {$/;" f
+verify_deps tools/scmp_app_inspector /^function verify_deps() {$/;" f
+version src/python/setup.py /^ version = os.environ["VERSION_RELEASE"],$/;" v
+write_file tests/util.py /^def write_file(path):$/;" f
+x32_arg_count_max src/arch-x32.h 32;" d
+x32_syscall_resolve_name src/arch-x32-syscalls.c /^int x32_syscall_resolve_name(const char *name)$/;" f
+x32_syscall_resolve_num src/arch-x32-syscalls.c /^const char *x32_syscall_resolve_num(int num)$/;" f
+x86_64_arg_count_max src/arch-x86_64.h 30;" d
+x86_64_arg_offset_hi src/arch-x86_64.h 35;" d
+x86_64_arg_offset_lo src/arch-x86_64.h 34;" d
+x86_64_syscall_resolve_name src/arch-x86_64-syscalls.c /^int x86_64_syscall_resolve_name(const char *name)$/;" f
+x86_64_syscall_resolve_num src/arch-x86_64-syscalls.c /^const char *x86_64_syscall_resolve_num(int num)$/;" f
+x86_64_syscall_table src/arch-x86_64-syscalls.c /^const struct arch_syscall_def x86_64_syscall_table[] = \\$/;" v typeref:struct:arch_syscall_def
+x86_arg_count_max src/arch-x86.h 31;" d
+x86_filter_rewrite src/arch-x86.c /^int x86_filter_rewrite(const struct arch_def *arch, bool strict,$/;" f
+x86_syscall_resolve_name src/arch-x86-syscalls.c /^int x86_syscall_resolve_name(const char *name)$/;" f
+x86_syscall_resolve_num src/arch-x86-syscalls.c /^const char *x86_syscall_resolve_num(int num)$/;" f
+x86_syscall_rewrite src/arch-x86.c /^int x86_syscall_rewrite(const struct arch_def *arch, bool strict, int *syscall)$/;" f
+x86_syscall_table src/arch-x86-syscalls.c /^static const struct arch_syscall_def x86_syscall_table[] = \\$/;" v typeref:struct:arch_syscall_def file:
--- /dev/null
+
+/*
+ * 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>.
+ */
+
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(void)
+{
+ scmp_filter_ctx ctx;
+ int status;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ return 1;
+
+ status = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(prctl), 0);
+ if (status < 0)
+ return 1;
+
+ status = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
+ if (status < 0)
+ return 1;
+
+#if 1
+ status = seccomp_load(ctx);
+ if (status < 0)
+ return 1;
+#endif
+
+ status = seccomp_reset(ctx, SCMP_ACT_ALLOW);
+ if (status < 0)
+ return 1;
+
+#if 0
+ status = seccomp_load(ctx);
+ if (status < 0)
+ return 1;
+#endif
+
+ write(2, "OK\n", 3);
+
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(ALLOW)
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+01-sim-allow all 0-350 N N N N N N ALLOW
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+01-sim-allow 50
+
+test type: bpf-valgrind
+
+# Testname
+01-sim-allow
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+/*
+ * Just like mode 1 seccomp we allow 4 syscalls:
+ * read, write, exit, and rt_sigreturn
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ f.add_rule_exactly(ALLOW, "read");
+ f.add_rule_exactly(ALLOW, "write");
+ f.add_rule_exactly(ALLOW, "close");
+ f.add_rule_exactly(ALLOW, "rt_sigreturn");
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+02-sim-basic all read 0 0x856B008 40 N N N ALLOW
+02-sim-basic all write 1 0x856B008 40 N N N ALLOW
+02-sim-basic all close 4 N N N N N ALLOW
+02-sim-basic all rt_sigreturn N N N N N N ALLOW
+02-sim-basic all open 0x856B008 4 N N N N KILL
+02-sim-basic x86 0-2 N N N N N N KILL
+02-sim-basic x86 7-172 N N N N N N KILL
+02-sim-basic x86 174-350 N N N N N N KILL
+02-sim-basic x86_64 4-14 N N N N N N KILL
+02-sim-basic x86_64 16-350 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+02-sim-basic 50
+
+test type: bpf-valgrind
+
+# Testname
+02-sim-basic
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ f.add_rule_exactly(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno()));
+ f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno()));
+ f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno()));
+ f.add_rule_exactly(ALLOW, "close");
+ f.add_rule_exactly(ALLOW, "rt_sigreturn");
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+03-sim-basic_chains all read 0 0x856B008 10 N N N ALLOW
+03-sim-basic_chains all read 1-10 0x856B008 10 N N N KILL
+03-sim-basic_chains all write 1-2 0x856B008 10 N N N ALLOW
+03-sim-basic_chains all write 3-10 0x856B008 10 N N N KILL
+03-sim-basic_chains all close N N N N N N ALLOW
+03-sim-basic_chains all rt_sigreturn N N N N N N ALLOW
+03-sim-basic_chains all open 0x856B008 4 N N N N KILL
+03-sim-basic_chains x86 0-2 N N N N N N KILL
+03-sim-basic_chains x86 7-172 N N N N N N KILL
+03-sim-basic_chains x86 174-350 N N N N N N KILL
+03-sim-basic_chains x86_64 4-14 N N N N N N KILL
+03-sim-basic_chains x86_64 16-350 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+03-sim-basic_chains 50
+
+test type: bpf-valgrind
+
+# Testname
+03-sim-basic_chains
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <limits.h>
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 3,
+ SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO),
+ SCMP_A1(SCMP_CMP_NE, 0x0),
+ SCMP_A2(SCMP_CMP_LT, SSIZE_MAX));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 3,
+ SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO),
+ SCMP_A1(SCMP_CMP_NE, 0x0),
+ SCMP_A2(SCMP_CMP_LT, SSIZE_MAX));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 3,
+ SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO),
+ SCMP_A1(SCMP_CMP_NE, 0x0),
+ SCMP_A2(SCMP_CMP_LT, SSIZE_MAX));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ f.add_rule_exactly(ALLOW, "open");
+ f.add_rule_exactly(ALLOW, "close");
+ f.add_rule_exactly(ALLOW, "read",
+ Arg(0, EQ, sys.stdin.fileno()),
+ Arg(1, NE, 0),
+ Arg(2, LT, sys.maxsize));
+ f.add_rule_exactly(ALLOW, "write",
+ Arg(0, EQ, sys.stdout.fileno()),
+ Arg(1, NE, 0),
+ Arg(2, LT, sys.maxsize));
+ f.add_rule_exactly(ALLOW, "write",
+ Arg(0, EQ, sys.stderr.fileno()),
+ Arg(1, NE, 0),
+ Arg(2, LT, sys.maxsize));
+ f.add_rule_exactly(ALLOW, "close");
+ f.add_rule_exactly(ALLOW, "rt_sigreturn");
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+04-sim-multilevel_chains all open 0x856B008 4 N N N N ALLOW
+04-sim-multilevel_chains all close 4 N N N N N ALLOW
+04-sim-multilevel_chains x86 read 0 0x856B008 0x7FFFFFFE N N N ALLOW
+04-sim-multilevel_chains x86_64 read 0 0x856B008 0x7FFFFFFFFFFFFFFE N N N ALLOW
+04-sim-multilevel_chains x86 read 0 0x856B008 0x7FFFFFFF N N N KILL
+04-sim-multilevel_chains x86_64 read 0 0x856B008 0x7FFFFFFFFFFFFFFF N N N KILL
+04-sim-multilevel_chains x86 read 0 0 0x7FFFFFFE N N N KILL
+04-sim-multilevel_chains x86_64 read 0 0 0x7FFFFFFFFFFFFFFE N N N KILL
+04-sim-multilevel_chains all read 1-10 0x856B008 0x7FFFFFFE N N N KILL
+04-sim-multilevel_chains x86 write 1-2 0x856B008 0x7FFFFFFE N N N ALLOW
+04-sim-multilevel_chains x86_64 write 1-2 0x856B008 0x7FFFFFFFFFFFFFFE N N N ALLOW
+04-sim-multilevel_chains x86 write 1-2 0 0x7FFFFFFE N N N KILL
+04-sim-multilevel_chains x86_64 write 1-2 0 0x7FFFFFFFFFFFFFFE N N N KILL
+04-sim-multilevel_chains x86 write 1-2 0x856B008 0x7FFFFFFF N N N KILL
+04-sim-multilevel_chains x86_64 write 1-2 0x856B008 0x7FFFFFFFFFFFFFFF N N N KILL
+04-sim-multilevel_chains all write 3-10 0x856B008 0x7FFFFFFE N N N KILL
+04-sim-multilevel_chains all rt_sigreturn N N N N N N ALLOW
+04-sim-multilevel_chains x86 0-2 N N N N N N KILL
+04-sim-multilevel_chains x86 7-172 N N N N N N KILL
+04-sim-multilevel_chains x86 174-350 N N N N N N KILL
+04-sim-multilevel_chains x86_64 4-14 N N N N N N KILL
+04-sim-multilevel_chains x86_64 16-350 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+04-sim-multilevel_chains 50
+
+test type: bpf-valgrind
+
+# Testname
+04-sim-multilevel_chains
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+#include <limits.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ int iter;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* NOTE - syscalls referenced by number to make the test simpler */
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1, 0);
+ if (rc != 0)
+ goto out;
+
+ /* same syscall, many chains */
+ for (iter = 0; iter < 100; iter++) {
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 3,
+ SCMP_A0(SCMP_CMP_EQ, iter),
+ SCMP_A1(SCMP_CMP_NE, 0x0),
+ SCMP_A2(SCMP_CMP_LT, SSIZE_MAX));
+ if (rc != 0)
+ goto out;
+ }
+
+ /* many syscalls, same chain */
+ for (iter = 100; iter < 200; iter++) {
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, iter, 1,
+ SCMP_A0(SCMP_CMP_NE, 0));
+ if (rc != 0)
+ goto out;
+ }
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 4, 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ # syscalls referenced by number to make the test simpler
+ f.add_rule_exactly(ALLOW, 1)
+ i = 0
+ while i < 100:
+ f.add_rule_exactly(ALLOW, 1000,
+ Arg(0, EQ, i),
+ Arg(1, NE, 0),
+ Arg(2, LT, sys.maxsize))
+ i += 1
+ i = 100
+ while i < 200:
+ f.add_rule_exactly(ALLOW, i,
+ Arg(0, NE, 0))
+ i += 1
+ f.add_rule_exactly(ALLOW, 4)
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
+
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+05-sim-long_jumps all 1 1 2 3 4 5 6 ALLOW
+05-sim-long_jumps all 2 N N N N N N KILL
+05-sim-long_jumps all 999 N N N N N N KILL
+05-sim-long_jumps x86 1000 0-5 0x856B008 0x7FFFFFFE N N N ALLOW
+05-sim-long_jumps x86_64 1000 0-5 0x856B008 0x7FFFFFFFFFFFFFFE N N N ALLOW
+05-sim-long_jumps x86 1000 95-99 0x856B008 0x7FFFFFFE N N N ALLOW
+05-sim-long_jumps x86_64 1000 95-99 0x856B008 0x7FFFFFFFFFFFFFFE N N N ALLOW
+05-sim-long_jumps x86 1000 100 0x856B008 0x7FFFFFFE N N N KILL
+05-sim-long_jumps x86_64 1000 100 0x856B008 0x7FFFFFFFFFFFFFFE N N N KILL
+05-sim-long_jumps all 1001 N N N N N N KILL
+05-sim-long_jumps all 99 1 N N N N N KILL
+05-sim-long_jumps all 100-105 1 N N N N N ALLOW
+05-sim-long_jumps all 195-199 1 N N N N N ALLOW
+05-sim-long_jumps all 200 1 N N N N N KILL
+05-sim-long_jumps all 3 N N N N N N KILL
+05-sim-long_jumps all 4 1 2 3 4 5 6 ALLOW
+05-sim-long_jumps all 5 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+05-sim-long_jumps 50
+
+test type: bpf-valgrind
+
+# Testname
+05-sim-long_jumps
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ERRNO(EPERM), SCMP_SYS(write), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_TRAP, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_TRACE(1234), SCMP_SYS(open), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import errno
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ f.add_rule(ALLOW, "read")
+ f.add_rule(ERRNO(errno.EPERM), "write")
+ f.add_rule(TRAP, "close")
+ f.add_rule(TRACE(1234), "open")
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+06-sim-actions all read 4 0x856B008 80 N N N ALLOW
+06-sim-actions all write 1 0x856B008 N N N N ERRNO(1)
+06-sim-actions all close 4 N N N N N TRAP
+06-sim-actions all open 0x856B008 4 N N N N TRACE(1234)
+06-sim-actions x86 0-2 N N N N N N KILL
+06-sim-actions x86 7-350 N N N N N N KILL
+06-sim-actions x86_64 4-350 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+06-sim-actions 50
+
+test type: bpf-valgrind
+
+# Testname
+06-sim-actions
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright IBM Corp. 2012
+ * Author: Ashley Lai <adlai@us.ibm.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* The next three seccomp_rule_add_exact() calls for read must
+ * go together in this order to catch an infinite loop. */
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
+ SCMP_A1(SCMP_CMP_EQ, 0x0));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ # the next three seccomp_rule_add_exact() calls for read must go together
+ # in this order to catch an infinite loop.
+ f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdout.fileno()))
+ f.add_rule(ALLOW, "read", Arg(1, EQ, 0))
+ f.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno()))
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+07-sim-db_bug_looping all read 1 0x856B008 10 N N N ALLOW
+07-sim-db_bug_looping all read 2-10 0 10 N N N ALLOW
+07-sim-db_bug_looping all read 0 0x856B008 10 N N N ALLOW
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+07-sim-db_bug_looping 50
+
+test type: bpf-valgrind
+
+# Testname
+07-sim-db_bug_looping
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* the syscall and argument numbers are all fake to make the test
+ * simpler */
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 2,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 1,
+ SCMP_A1(SCMP_CMP_EQ, 1));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1001, 1,
+ SCMP_A1(SCMP_CMP_EQ, 1));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1001, 2,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1002, 4,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2),
+ SCMP_A3(SCMP_CMP_EQ, 3));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1002, 2,
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1003, 2,
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1003, 4,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2),
+ SCMP_A3(SCMP_CMP_EQ, 3));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1004, 4,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2),
+ SCMP_A3(SCMP_CMP_EQ, 3));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1004, 2,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 11));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1004, 4,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2),
+ SCMP_A3(SCMP_CMP_EQ, 33));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1004, 2,
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1005, 2,
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1005, 4,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2),
+ SCMP_A3(SCMP_CMP_EQ, 3));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1005, 2,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 11));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1005, 4,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2),
+ SCMP_A3(SCMP_CMP_EQ, 33));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1006, 2,
+ SCMP_A1(SCMP_CMP_NE, 1),
+ SCMP_A2(SCMP_CMP_EQ, 0));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1006, 2,
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1006, 1,
+ SCMP_A1(SCMP_CMP_NE, 1));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_TRAP, 1007, 2,
+ SCMP_A2(SCMP_CMP_EQ, 1),
+ SCMP_A3(SCMP_CMP_EQ, 3));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1007, 2,
+ SCMP_A2(SCMP_CMP_EQ, 1),
+ SCMP_A3(SCMP_CMP_NE, 3));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1007, 1,
+ SCMP_A3(SCMP_CMP_NE, 3));
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ # the syscall and argument numbers are all fake to make the test simpler
+ f.add_rule_exactly(ALLOW, 1000,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1))
+ f.add_rule_exactly(ALLOW, 1000,
+ Arg(1, EQ, 1))
+
+ f.add_rule_exactly(ALLOW, 1001,
+ Arg(1, EQ, 1))
+ f.add_rule_exactly(ALLOW, 1001,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1))
+
+ f.add_rule_exactly(ALLOW, 1002,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2),
+ Arg(3, EQ, 3))
+ f.add_rule_exactly(ALLOW, 1002,
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2))
+
+ f.add_rule_exactly(ALLOW, 1003,
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2))
+ f.add_rule_exactly(ALLOW, 1003,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2),
+ Arg(3, EQ, 3))
+
+ f.add_rule_exactly(ALLOW, 1004,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2),
+ Arg(3, EQ, 3))
+ f.add_rule_exactly(ALLOW, 1004,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 11))
+ f.add_rule_exactly(ALLOW, 1004,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2),
+ Arg(3, EQ, 33))
+ f.add_rule_exactly(ALLOW, 1004,
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2))
+
+ f.add_rule_exactly(ALLOW, 1005,
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2))
+ f.add_rule_exactly(ALLOW, 1005,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2),
+ Arg(3, EQ, 3))
+ f.add_rule_exactly(ALLOW, 1005,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 11))
+ f.add_rule_exactly(ALLOW, 1005,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2),
+ Arg(3, EQ, 33))
+
+ f.add_rule_exactly(ALLOW, 1006,
+ Arg(1, NE, 1),
+ Arg(2, EQ, 0))
+ f.add_rule_exactly(ALLOW, 1006,
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2))
+ f.add_rule_exactly(ALLOW, 1006,
+ Arg(1, NE, 1))
+
+ f.add_rule_exactly(TRAP, 1007,
+ Arg(2, EQ, 1),
+ Arg(3, EQ, 3))
+ f.add_rule_exactly(ALLOW, 1007,
+ Arg(2, EQ, 1),
+ Arg(3, NE, 3))
+ f.add_rule_exactly(ALLOW, 1007,
+ Arg(3, NE, 3))
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+08-sim-subtree_checks all 1000 0-10 1 N N N N ALLOW
+08-sim-subtree_checks all 1000 0-10 0 N N N N KILL
+08-sim-subtree_checks all 1001 0-10 1 N N N N ALLOW
+08-sim-subtree_checks all 1001 0-10 0 N N N N KILL
+08-sim-subtree_checks all 1002 0-5 1 2 0-5 N N ALLOW
+08-sim-subtree_checks all 1002 0-5 2 1 0-5 N N KILL
+08-sim-subtree_checks all 1003 0-5 1 2 0-5 N N ALLOW
+08-sim-subtree_checks all 1003 0-5 2 1 0-5 N N KILL
+08-sim-subtree_checks all 1004 0 11 5-10 10 10 1-5 ALLOW
+08-sim-subtree_checks all 1004 0 1 2 0-5 N N ALLOW
+08-sim-subtree_checks all 1004 1-5 1 2 0-5 N N ALLOW
+08-sim-subtree_checks all 1004 1-5 1 2 30-35 N N ALLOW
+08-sim-subtree_checks all 1004 1-5 2 1 30-35 N N KILL
+08-sim-subtree_checks all 1005 0 11 5-10 10 10 1-5 ALLOW
+08-sim-subtree_checks all 1005 0 1 2 0-5 N N ALLOW
+08-sim-subtree_checks all 1005 1-5 1 2 0-5 N N ALLOW
+08-sim-subtree_checks all 1005 1-5 1 2 30-35 N N ALLOW
+08-sim-subtree_checks all 1005 1-5 2 1 30-35 N N KILL
+08-sim-subtree_checks all 1006 0-10 1 2 N N N ALLOW
+08-sim-subtree_checks all 1006 0-10 1 3 N N N KILL
+08-sim-subtree_checks all 1006 10 2-100 2 N N N ALLOW
+08-sim-subtree_checks all 1007 0 0 1 3 N N TRAP
+08-sim-subtree_checks all 1007 1 1 1 0-2 1 1 ALLOW
+08-sim-subtree_checks all 1007 1 1 2 0-2 1 1 ALLOW
+08-sim-subtree_checks all 1007 1 1 2 4-6 1 1 ALLOW
+08-sim-subtree_checks all 1007 1 1 0 3 1 1 KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+08-sim-subtree_checks 50
+
+
+test type: bpf-valgrind
+
+# Testname
+08-sim-subtree_checks
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* the syscall and argument numbers are all fake to make the test
+ * simpler */
+
+ rc = seccomp_syscall_priority(ctx, 1000, 3);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_syscall_priority(ctx, 1001, 2);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_syscall_priority(ctx, 1002, 1);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 2,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1001, 1,
+ SCMP_A0(SCMP_CMP_EQ, 0));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1002, 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ # the syscall and argument numbers are all fake to make the test simpler
+ f.syscall_priority(1000, 3)
+ f.syscall_priority(1001, 2)
+ f.syscall_priority(1002, 1)
+ f.add_rule_exactly(ALLOW, 1000, Arg(0, EQ, 0), Arg(1, EQ, 1))
+ f.add_rule_exactly(ALLOW, 1001, Arg(0, EQ, 0))
+ f.add_rule_exactly(ALLOW, 1002)
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+09-sim-syscall_priority_pre all 999 N N N N N N KILL
+09-sim-syscall_priority_pre all 1000-1002 0 1 N N N N ALLOW
+09-sim-syscall_priority_pre all 1000 0 2 N N N N KILL
+09-sim-syscall_priority_pre all 1001-1002 0 2 N N N N ALLOW
+09-sim-syscall_priority_pre all 1000-1001 1 1 N N N N KILL
+09-sim-syscall_priority_pre all 1003 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+09-sim-syscall_priority_pre 50
+
+test type: bpf-valgrind
+
+# Testname
+09-sim-syscall_priority_pre
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* the syscall and argument numbers are all fake to make the test
+ * simpler */
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 2,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1001, 1,
+ SCMP_A0(SCMP_CMP_EQ, 0));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1002, 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_syscall_priority(ctx, 1000, 3);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_syscall_priority(ctx, 1001, 2);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_syscall_priority(ctx, 1002, 1);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ # the syscall and argument numbers are all fake to make the test simpler
+ f.add_rule_exactly(ALLOW, 1000, Arg(0, EQ, 0), Arg(1, EQ, 1))
+ f.add_rule_exactly(ALLOW, 1001, Arg(0, EQ, 0))
+ f.add_rule_exactly(ALLOW, 1002)
+ f.syscall_priority(1000, 3)
+ f.syscall_priority(1001, 2)
+ f.syscall_priority(1002, 1)
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+10-sim-syscall_priority_post all 999 N N N N N N KILL
+10-sim-syscall_priority_post all 1000-1002 0 1 N N N N ALLOW
+10-sim-syscall_priority_post all 1000 0 2 N N N N KILL
+10-sim-syscall_priority_post all 1001-1002 0 2 N N N N ALLOW
+10-sim-syscall_priority_post all 1000-1001 1 1 N N N N KILL
+10-sim-syscall_priority_post all 1003 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+10-sim-syscall_priority_post 50
+
+test type: bpf-valgrind
+
+# Testname
+10-sim-syscall_priority_post
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright IBM Corp. 2012
+ * Author: Corey Bryant <coreyb@linux.vnet.ibm.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>.
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ scmp_filter_ctx ctx;
+
+ /* seccomp_init errors */
+ ctx = seccomp_init(SCMP_ACT_ALLOW + 1);
+ if (ctx != NULL)
+ return -1;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ return -1;
+ seccomp_release(ctx);
+ ctx = NULL;
+
+ /* seccomp_reset error */
+ rc = seccomp_reset(ctx, SCMP_ACT_KILL + 1);
+ if (rc != -EINVAL)
+ return -1;
+ rc = seccomp_reset(ctx, SCMP_ACT_KILL);
+ if (rc != -EINVAL)
+ return -1;
+
+ /* seccomp_load error */
+ rc = seccomp_load(ctx);
+ if (rc != -EINVAL)
+ return -1;
+
+ /* seccomp_syscall_priority errors */
+ rc = seccomp_syscall_priority(ctx, SCMP_SYS(read), 1);
+ if (rc != -EINVAL)
+ return -1;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ return -1;
+ else {
+ rc = seccomp_syscall_priority(ctx, -10, 1);
+ if (rc != -EINVAL)
+ return -1;
+ }
+ seccomp_release(ctx);
+ ctx = NULL;
+
+ /* seccomp_rule_add errors */
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
+ SCMP_A0(SCMP_CMP_EQ, 0));
+ if (rc != -EINVAL)
+ return -1;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ return -1;
+ else {
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
+ if (rc != -EPERM)
+ return -1;
+ rc = seccomp_rule_add(ctx, SCMP_ACT_KILL - 1, SCMP_SYS(read), 0);
+ if (rc != -EINVAL)
+ return -1;
+ rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(read), 6);
+ if (rc != -EINVAL)
+ return -1;
+ rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(read), 7,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 0),
+ SCMP_A2(SCMP_CMP_EQ, 0),
+ SCMP_A3(SCMP_CMP_EQ, 0),
+ SCMP_A4(SCMP_CMP_EQ, 0),
+ SCMP_A5(SCMP_CMP_EQ, 0),
+ SCMP_CMP(6, SCMP_CMP_EQ, 0));
+ if (rc != -EINVAL)
+ return -1;
+ rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(read), 1,
+ SCMP_A0(_SCMP_CMP_MIN, 0));
+ if (rc != -EINVAL)
+ return -1;
+ rc = seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(read), 1,
+ SCMP_A0(_SCMP_CMP_MAX, 0));
+ if (rc != -EINVAL)
+ return -1;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, -10001, 0);
+ if (rc != -EDOM)
+ return -1;
+ }
+ seccomp_release(ctx);
+ ctx = NULL;
+
+ /* seccomp_rule_add_exact error */
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ return -1;
+ if (seccomp_arch_native() != SCMP_ARCH_X86) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
+ if (rc != 0)
+ return -1;
+ rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE);
+ if (rc != 0)
+ return -1;
+ }
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, SCMP_SYS(socket), 1,
+ SCMP_A0(SCMP_CMP_EQ, 2));
+ if (rc != -EINVAL)
+ return -1;
+ seccomp_release(ctx);
+ ctx = NULL;
+
+ /* seccomp_export_pfc errors */
+ rc = seccomp_export_pfc(ctx, STDOUT_FILENO);
+ if (rc != -EINVAL)
+ return -1;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ return -1;
+ else {
+ rc = seccomp_export_pfc(ctx, sysconf(_SC_OPEN_MAX) - 1);
+ if (rc != EBADF)
+ return -1;
+ }
+ seccomp_release(ctx);
+ ctx = NULL;
+
+ /* seccomp_export_bpf errors */
+ rc = seccomp_export_bpf(ctx, STDOUT_FILENO);
+ if (rc != -EINVAL)
+ return -1;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ return -1;
+ else {
+ rc = seccomp_export_bpf(ctx, sysconf(_SC_OPEN_MAX) - 1);
+ if (rc != -EBADF)
+ return -1;
+ }
+ seccomp_release(ctx);
+ ctx = NULL;
+
+ return 0;
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test():
+ # this test differs from the native test for obvious reasons
+ try:
+ f = SyscallFilter(ALLOW + 1)
+ except RuntimeError:
+ pass
+
+ f = SyscallFilter(ALLOW)
+ try:
+ f.reset(KILL + 1)
+ except ValueError:
+ pass
+
+ f = SyscallFilter(ALLOW)
+ try:
+ f.syscall_priority(-10000, 1)
+ except RuntimeError:
+ pass
+
+ f = SyscallFilter(ALLOW)
+ try:
+ f.add_rule(ALLOW, "read")
+ except RuntimeError:
+ pass
+ try:
+ f.add_rule(KILL - 1, "read")
+ except RuntimeError:
+ pass
+ try:
+ f.add_rule(KILL, "read",
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2),
+ Arg(3, EQ, 3),
+ Arg(4, EQ, 4),
+ Arg(5, EQ, 5),
+ Arg(6, EQ, 6),
+ Arg(7, EQ, 7))
+ except RuntimeError:
+ pass
+ try:
+ f.add_rule(KILL, -1001)
+ except RuntimeError:
+ pass
+
+ f = SyscallFilter(ALLOW)
+ if not f.exist_arch(Arch.X86):
+ f.add_arch(Arch.X86)
+ f.remove_arch(Arch.NATIVE)
+ try:
+ f.add_rule_exactly(KILL, "socket", Arg(0, EQ, 2))
+ except RuntimeError:
+ pass
+
+test()
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: basic
+
+# Test command
+11-basic-basic_errors
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ /* the syscall and argument numbers are all fake to make the test
+ * simpler */
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 3,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_EQ, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 3,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_MASKED_EQ, 0x00ff, 1),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 3,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_MASKED_EQ, 0xffff, 11),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 3,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_MASKED_EQ, 0xffff, 111),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 1000, 3,
+ SCMP_A0(SCMP_CMP_EQ, 0),
+ SCMP_A1(SCMP_CMP_MASKED_EQ, 0xff00, 1000),
+ SCMP_A2(SCMP_CMP_EQ, 2));
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ # the syscall and argument numbers are all fake to make the test simpler
+ f.add_rule_exactly(ALLOW, 1000,
+ Arg(0, EQ, 0),
+ Arg(1, EQ, 1),
+ Arg(2, EQ, 2))
+ f.add_rule_exactly(ALLOW, 1000,
+ Arg(0, EQ, 0),
+ Arg(1, MASKED_EQ, 0x00ff, 1),
+ Arg(2, EQ, 2))
+ f.add_rule_exactly(ALLOW, 1000,
+ Arg(0, EQ, 0),
+ Arg(1, MASKED_EQ, 0xffff, 11),
+ Arg(2, EQ, 2))
+ f.add_rule_exactly(ALLOW, 1000,
+ Arg(0, EQ, 0),
+ Arg(1, MASKED_EQ, 0xffff, 111),
+ Arg(2, EQ, 2))
+ f.add_rule_exactly(ALLOW, 1000,
+ Arg(0, EQ, 0),
+ Arg(1, MASKED_EQ, 0xff00, 1000),
+ Arg(2, EQ, 2))
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+12-sim-basic_masked_ops all 1000 0 1 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 0x01 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 0x02-0x0A 2 N N N KILL
+12-sim-basic_masked_ops all 1000 0 0x101 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 11 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 0x0B 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 0x0C-0x6E 2 N N N KILL
+12-sim-basic_masked_ops all 1000 0 0x1000B 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 111 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 0x6F 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 0x70-0x100 2 N N N KILL
+12-sim-basic_masked_ops all 1000 0 0x102-0x200 2 N N N KILL
+12-sim-basic_masked_ops all 1000 0 0x10002-0x1000A 2 N N N KILL
+12-sim-basic_masked_ops all 1000 0 0x1000C-0x1006E 2 N N N KILL
+12-sim-basic_masked_ops all 1000 0 0x1006F 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 1000 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 0x3E8 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 0x2FF 2 N N N KILL
+12-sim-basic_masked_ops all 1000 0 0x300-0x3FF 2 N N N ALLOW
+12-sim-basic_masked_ops all 1000 0 0x400 2 N N N KILL
+12-sim-basic_masked_ops all 1000 0 0x402-0x4FF 2 N N N KILL
+12-sim-basic_masked_ops all 1000 0 0x10300-0x103FF 2 N N N ALLOW
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+12-sim-basic_masked_ops 50
+
+test type: bpf-valgrind
+
+# Testname
+12-sim-basic_masked_ops
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ uint32_t val = (uint32_t)(-1);
+ scmp_filter_ctx ctx;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ goto out;
+
+ rc = seccomp_attr_get(ctx, SCMP_FLTATR_ACT_DEFAULT, &val);
+ if (rc != 0)
+ goto out;
+ if (val != SCMP_ACT_ALLOW) {
+ rc = -1;
+ goto out;
+ }
+ rc = seccomp_attr_set(ctx, SCMP_FLTATR_ACT_DEFAULT, val);
+ if (rc != -EACCES) {
+ rc = -1;
+ goto out;
+ }
+
+ rc = seccomp_attr_set(ctx, SCMP_FLTATR_ACT_BADARCH, SCMP_ACT_ALLOW);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_attr_get(ctx, SCMP_FLTATR_ACT_BADARCH, &val);
+ if (rc != 0)
+ goto out;
+ if (val != SCMP_ACT_ALLOW) {
+ rc = -1;
+ goto out;
+ }
+
+ rc = seccomp_attr_set(ctx, SCMP_FLTATR_CTL_NNP, 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_attr_get(ctx, SCMP_FLTATR_CTL_NNP, &val);
+ if (rc != 0)
+ goto out;
+ if (val != 0) {
+ rc = -1;
+ goto out;
+ }
+
+ rc = 0;
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test():
+ f = SyscallFilter(ALLOW)
+ if f.get_attr(Attr.ACT_DEFAULT) != ALLOW:
+ raise RuntimeError("Failed getting Attr.ACT_DEFAULT")
+ try:
+ f.set_attr(Attr.ACT_DEFAULT, ALLOW)
+ except RuntimeError:
+ pass
+ f.set_attr(Attr.ACT_BADARCH, ALLOW)
+ if f.get_attr(Attr.ACT_BADARCH) != ALLOW:
+ raise RuntimeError("Failed getting Attr.ACT_BADARCH")
+ f.set_attr(Attr.CTL_NNP, 0)
+ if f.get_attr(Attr.CTL_NNP) != 0:
+ raise RuntimeError("Failed getting Attr.CTL_NNP")
+
+test()
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.com>
+#
+
+test type: basic
+
+# Test command
+13-basic-attrs
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_reset(ctx, SCMP_ACT_KILL);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ f.add_rule(ALLOW, "read")
+ f.reset()
+ f.add_rule(ALLOW, "write")
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+14-sim-reset all read 0 0x856B008 40 N N N KILL
+14-sim-reset all write 1 0x856B008 40 N N N ALLOW
+14-sim-reset all close 4 N N N N N KILL
+14-sim-reset all rt_sigreturn N N N N N N KILL
+14-sim-reset all open 0x856B008 4 N N N N KILL
+14-sim-reset x86 0-3 N N N N N N KILL
+14-sim-reset x86 5-360 N N N N N N KILL
+14-sim-reset x86_64 0 N N N N N N KILL
+14-sim-reset x86_64 2-360 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+14-sim-reset 50
+
+test type: bpf-valgrind
+
+# Testname
+14-sim-reset
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <string.h>
+
+#include <seccomp.h>
+
+int main(int argc, char *argv[])
+{
+ char *name;
+
+ if (seccomp_syscall_resolve_name("open") != __NR_open)
+ return 1;
+ if (seccomp_syscall_resolve_name("socket") != __NR_socket)
+ return 1;
+ if (seccomp_syscall_resolve_name("INVALID") != __NR_SCMP_ERROR)
+ return 1;
+
+ if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE,
+ "open") != __NR_open)
+ return 1;
+ if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE,
+ "socket") != __NR_socket)
+ return 1;
+ if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE,
+ "INVALID") != __NR_SCMP_ERROR)
+ return 1;
+
+ name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_open);
+ if (name == NULL || strcmp(name, "open") != 0)
+ return 1;
+ name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_socket);
+ if (name == NULL || strcmp(name, "socket") != 0)
+ return 1;
+ name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE,
+ __NR_SCMP_ERROR);
+ if (name != NULL)
+ return 1;
+
+ return 0;
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test():
+ f = SyscallFilter(KILL)
+ # this differs from the native test as we don't support the syscall
+ # resolution functions by themselves
+ f.add_rule(ALLOW, "open")
+ f.add_rule(ALLOW, "socket")
+ try:
+ f.add_rule(ALLOW, "INVALID")
+ except RuntimeError:
+ pass
+
+ sys_num = resolve_syscall(Arch.NATIVE, "open")
+ sys_name = resolve_syscall(Arch.NATIVE, sys_num)
+ if (sys_name != "open"):
+ raise RuntimeError("Test failure")
+ sys_num = resolve_syscall(Arch.NATIVE, "socket")
+ sys_name = resolve_syscall(Arch.NATIVE, sys_num)
+ if (sys_name != "socket"):
+ raise RuntimeError("Test failure")
+
+test()
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com>
+#
+
+test type: basic
+
+# Test command
+15-basic-resolver
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ if (seccomp_arch_exist(ctx, SCMP_ARCH_X86)) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
+ if (rc != 0)
+ goto out;
+ }
+ if (seccomp_arch_exist(ctx, SCMP_ARCH_X86_64)) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_X86_64);
+ if (rc != 0)
+ goto out;
+ }
+ if (seccomp_arch_exist(ctx, SCMP_ARCH_X32)) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_X32);
+ if (rc != 0)
+ goto out;
+ }
+ if (seccomp_arch_exist(ctx, SCMP_ARCH_ARM)) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_ARM);
+ if (rc != 0)
+ goto out;
+ }
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(shutdown), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ if not f.exist_arch(Arch.X86):
+ f.add_arch(Arch.X86)
+ if not f.exist_arch(Arch.X86_64):
+ f.add_arch(Arch.X86_64)
+ if not f.exist_arch(Arch.X32):
+ f.add_arch(Arch.X32)
+ if not f.exist_arch(Arch.ARM):
+ f.add_arch(Arch.ARM)
+ 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()))
+ f.add_rule(ALLOW, "close")
+ f.add_rule(ALLOW, "socket")
+ f.add_rule(ALLOW, "connect")
+ f.add_rule(ALLOW, "shutdown")
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+16-sim-arch_basic +all read 0 0x856B008 10 N N N ALLOW
+16-sim-arch_basic +all read 1-10 0x856B008 10 N N N KILL
+16-sim-arch_basic +all write 1-2 0x856B008 10 N N N ALLOW
+16-sim-arch_basic +all write 3-10 0x856B008 10 N N N KILL
+16-sim-arch_basic +all close N N N N N N ALLOW
+16-sim-arch_basic +all open 0x856B008 4 N N N N KILL
+16-sim-arch_basic +x86 socket 1 N N N N N ALLOW
+16-sim-arch_basic +x86 connect 3 N N N N N ALLOW
+16-sim-arch_basic +x86 shutdown 13 N N N N N ALLOW
+16-sim-arch_basic +x86_64 socket 0 1 2 N N N ALLOW
+16-sim-arch_basic +x86_64 connect 0 1 2 N N N ALLOW
+16-sim-arch_basic +x86_64 shutdown 0 1 2 N N N ALLOW
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+16-sim-arch_basic 50
+
+test type: bpf-valgrind
+
+# Testname
+16-sim-arch_basic
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+#include <errno.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx_64, ctx_32;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out_all;
+
+ ctx_32 = seccomp_init(SCMP_ACT_KILL);
+ if (ctx_32 == NULL)
+ goto out_all;
+ ctx_64 = seccomp_init(SCMP_ACT_KILL);
+ if (ctx_64 == NULL)
+ goto out_all;
+
+ if (seccomp_arch_exist(ctx_32, SCMP_ARCH_X86) == -EEXIST) {
+ rc = seccomp_arch_add(ctx_32, SCMP_ARCH_X86);
+ if (rc != 0)
+ goto out_all;
+ rc = seccomp_arch_remove(ctx_32, SCMP_ARCH_NATIVE);
+ if (rc != 0)
+ goto out_all;
+ }
+ if (seccomp_arch_exist(ctx_64, SCMP_ARCH_X86_64) == -EEXIST) {
+ rc = seccomp_arch_add(ctx_64, SCMP_ARCH_X86_64);
+ if (rc != 0)
+ goto out_all;
+ rc = seccomp_arch_remove(ctx_64, SCMP_ARCH_NATIVE);
+ if (rc != 0)
+ goto out_all;
+ }
+
+ rc = seccomp_rule_add(ctx_32, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO));
+ if (rc != 0)
+ goto out_all;
+
+ rc = seccomp_rule_add(ctx_32, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO));
+ if (rc != 0)
+ goto out_all;
+
+ rc = seccomp_rule_add(ctx_32, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO));
+ if (rc != 0)
+ goto out_all;
+
+ rc = seccomp_rule_add(ctx_32, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out_all;
+
+ rc = seccomp_rule_add(ctx_64, SCMP_ACT_ALLOW, SCMP_SYS(socket), 0);
+ if (rc != 0)
+ goto out_all;
+
+ rc = seccomp_rule_add(ctx_64, SCMP_ACT_ALLOW, SCMP_SYS(connect), 0);
+ if (rc != 0)
+ goto out_all;
+
+ rc = seccomp_rule_add(ctx_64, SCMP_ACT_ALLOW, SCMP_SYS(shutdown), 0);
+ if (rc != 0)
+ goto out_all;
+
+ rc = seccomp_merge(ctx_64, ctx_32);
+ if (rc != 0)
+ goto out_all;
+
+ /* NOTE: ctx_32 is no longer valid at this point */
+
+ rc = util_filter_output(&opts, ctx_64);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx_64);
+ return (rc < 0 ? -rc : rc);
+out_all:
+ seccomp_release(ctx_32);
+ goto out;
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f32 = SyscallFilter(KILL)
+ f64 = SyscallFilter(KILL)
+ if not f32.exist_arch(Arch.X86):
+ f32.add_arch(Arch.X86)
+ f32.remove_arch(Arch.NATIVE)
+ if not f64.exist_arch(Arch.X86_64):
+ f64.add_arch(Arch.X86_64)
+ f64.remove_arch(Arch.NATIVE)
+ f32.add_rule(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno()))
+ f32.add_rule(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno()))
+ f32.add_rule(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno()))
+ f32.add_rule(ALLOW, "close")
+ f64.add_rule(ALLOW, "socket")
+ f64.add_rule(ALLOW, "connect")
+ f64.add_rule(ALLOW, "shutdown")
+ f64.merge(f32)
+ return f64
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+17-sim-arch_merge +x86 read 0 0x856B008 10 N N N ALLOW
+17-sim-arch_merge +x86 read 1-10 0x856B008 10 N N N KILL
+17-sim-arch_merge +x86 write 1-2 0x856B008 10 N N N ALLOW
+17-sim-arch_merge +x86 write 3-10 0x856B008 10 N N N KILL
+17-sim-arch_merge +x86 close N N N N N N ALLOW
+17-sim-arch_merge +x86 open 0x856B008 4 N N N N KILL
+17-sim-arch_merge +x86_64 socket 0 1 2 N N N ALLOW
+17-sim-arch_merge +x86_64 connect 0 1 2 N N N ALLOW
+17-sim-arch_merge +x86_64 shutdown 0 1 2 N N N ALLOW
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+17-sim-arch_merge 50
+
+test type: bpf-valgrind
+
+# Testname
+17-sim-arch_merge
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_ALLOW);
+ if (ctx == NULL)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, SCMP_SYS(read), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_KILL, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_KILL, SCMP_SYS(rt_sigreturn), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(ALLOW)
+ f.add_rule_exactly(KILL, "read", Arg(0, EQ, sys.stdin.fileno()));
+ f.add_rule_exactly(KILL, "write", Arg(0, EQ, sys.stdout.fileno()));
+ f.add_rule_exactly(KILL, "write", Arg(0, EQ, sys.stderr.fileno()));
+ f.add_rule_exactly(KILL, "close");
+ f.add_rule_exactly(KILL, "rt_sigreturn");
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+18-sim-basic_whitelist all read 0 0x856B008 10 N N N KILL
+18-sim-basic_whitelist all read 1-10 0x856B008 10 N N N ALLOW
+18-sim-basic_whitelist all write 1-2 0x856B008 10 N N N KILL
+18-sim-basic_whitelist all write 3-10 0x856B008 10 N N N ALLOW
+18-sim-basic_whitelist all close N N N N N N KILL
+18-sim-basic_whitelist all rt_sigreturn N N N N N N KILL
+18-sim-basic_whitelist all open 0x856B008 4 N N N N ALLOW
+18-sim-basic_whitelist x86 0-2 N N N N N N ALLOW
+18-sim-basic_whitelist x86 7-172 N N N N N N ALLOW
+18-sim-basic_whitelist x86 174-350 N N N N N N ALLOW
+18-sim-basic_whitelist x86_64 4-14 N N N N N N ALLOW
+18-sim-basic_whitelist x86_64 16-350 N N N N N N ALLOW
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+18-sim-basic_whitelist 50
+
+test type: bpf-valgrind
+
+# Testname
+18-sim-basic_whitelist
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ if (seccomp_arch_native() != SCMP_ARCH_X86) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_arch_remove(ctx, SCMP_ARCH_NATIVE);
+ if (rc != 0)
+ goto out;
+ }
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tuxcall), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(tuxcall), 0);
+ if (rc != -EDOM)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ if not system_arch() == Arch.X86:
+ f.add_arch(Arch.X86)
+ f.remove_arch(Arch.NATIVE)
+ f.add_rule(ALLOW, "tuxcall")
+ try:
+ f.add_rule_exactly(ALLOW, "tuxcall")
+ except RuntimeError:
+ pass
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+19-sim-missing_syscalls +x86 0-350 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+19-sim-missing_syscalls 50
+
+test type: bpf-valgrind
+
+# Testname
+19-sim-missing_syscalls
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ int action;
+ scmp_filter_ctx ctx;
+
+ rc = util_action_parse(argv[1]);
+ if (rc == -1)
+ goto out;
+ action = rc;
+
+ if (action == SCMP_ACT_TRAP) {
+ rc = util_trap_install();
+ if (rc != 0)
+ goto out;
+ }
+
+ ctx = seccomp_init(action);
+ if (ctx == NULL)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_load(ctx);
+ if (rc != 0)
+ goto out;
+
+ rc = util_file_write("/dev/null");
+ if (rc != 0)
+ goto out;
+
+ rc = 160;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test():
+ action = util.parse_action(sys.argv[1])
+ if action == TRAP:
+ util.install_trap()
+ f = SyscallFilter(action)
+ f.add_rule_exactly(ALLOW, "rt_sigreturn")
+ f.add_rule_exactly(ALLOW, "exit_group")
+ f.load()
+ try:
+ util.write_file("/dev/null")
+ except OSError as ex:
+ quit(ex.errno)
+ quit(160)
+
+test()
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com
+#
+
+test type: live
+
+# Testname Result
+20-live-basic_die KILL
+20-live-basic_die TRAP
+20-live-basic_die ERRNO
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ scmp_filter_ctx ctx;
+
+ rc = util_action_parse(argv[1]);
+ if (rc != SCMP_ACT_ALLOW) {
+ rc = 1;
+ goto out;
+ }
+
+ rc = util_trap_install();
+ if (rc != 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_TRAP);
+ if (ctx == NULL)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_load(ctx);
+ if (rc != 0)
+ goto out;
+
+ rc = util_file_write("/dev/null");
+ if (rc != 0)
+ goto out;
+
+ rc = 160;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test():
+ action = util.parse_action(sys.argv[1])
+ if not action == ALLOW:
+ quit(1)
+ util.install_trap()
+ f = SyscallFilter(TRAP)
+ # NOTE: additional syscalls required for python
+ f.add_rule_exactly(ALLOW, "stat")
+ f.add_rule_exactly(ALLOW, "fstat")
+ f.add_rule_exactly(ALLOW, "open")
+ f.add_rule_exactly(ALLOW, "mmap")
+ f.add_rule_exactly(ALLOW, "munmap")
+ f.add_rule_exactly(ALLOW, "read")
+ f.add_rule_exactly(ALLOW, "write")
+ f.add_rule_exactly(ALLOW, "close")
+ f.add_rule_exactly(ALLOW, "rt_sigaction")
+ f.add_rule_exactly(ALLOW, "rt_sigreturn")
+ f.add_rule_exactly(ALLOW, "exit_group")
+ f.load()
+ try:
+ util.write_file("/dev/null")
+ except OSError as ex:
+ quit(ex.errno)
+ quit(160)
+
+test()
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com
+#
+
+test type: live
+
+# Testname Result
+21-live-basic_allow ALLOW
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Author: Paul Moore <pmoore@redhat.com>, Vitaly Shukela <vi0oss@gmail.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+ struct scmp_arg_cmp arg_cmp;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ arg_cmp = SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO);
+ rc = seccomp_rule_add_exact_array(ctx, SCMP_ACT_ALLOW,
+ SCMP_SYS(read), 1, &arg_cmp);
+ if (rc != 0)
+ goto out;
+
+ arg_cmp = SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO);
+ rc = seccomp_rule_add_exact_array(ctx, SCMP_ACT_ALLOW,
+ SCMP_SYS(write), 1, &arg_cmp);
+ if (rc != 0)
+ goto out;
+
+ arg_cmp = SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO);
+ rc = seccomp_rule_add_exact_array(ctx, SCMP_ACT_ALLOW,
+ SCMP_SYS(write), 1, &arg_cmp);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact_array(ctx, SCMP_ACT_ALLOW,
+ SCMP_SYS(close), 0, NULL);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact_array(ctx, SCMP_ACT_ALLOW,
+ SCMP_SYS(rt_sigreturn), 0, NULL);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+# NOTE: this is identical to 03-sim-basic_chains.py but is here to satisfy the
+# need for an equivalent Python test for each native C test
+
+import argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ f.add_rule_exactly(ALLOW, "read", Arg(0, EQ, sys.stdin.fileno()));
+ f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stdout.fileno()));
+ f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, sys.stderr.fileno()));
+ f.add_rule_exactly(ALLOW, "close");
+ f.add_rule_exactly(ALLOW, "rt_sigreturn");
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Author: Vitaly Shukela <vi0oss@gmail.com>
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+22-sim-basic_chains_array all read 0 0x856B008 10 N N N ALLOW
+22-sim-basic_chains_array all read 1-10 0x856B008 10 N N N KILL
+22-sim-basic_chains_array all write 1-2 0x856B008 10 N N N ALLOW
+22-sim-basic_chains_array all write 3-10 0x856B008 10 N N N KILL
+22-sim-basic_chains_array all close N N N N N N ALLOW
+22-sim-basic_chains_array all rt_sigreturn N N N N N N ALLOW
+22-sim-basic_chains_array all open 0x856B008 4 N N N N KILL
+22-sim-basic_chains_array x86 0-2 N N N N N N KILL
+22-sim-basic_chains_array x86 7-172 N N N N N N KILL
+22-sim-basic_chains_array x86 174-350 N N N N N N KILL
+22-sim-basic_chains_array x86_64 4-14 N N N N N N KILL
+22-sim-basic_chains_array x86_64 16-350 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+22-sim-basic_chains_array 50
+
+test type: bpf-valgrind
+
+# Testname
+22-sim-basic_chains_array
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <unistd.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ if (seccomp_arch_exist(ctx, SCMP_ARCH_X86)) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_X86);
+ if (rc != 0)
+ goto out;
+ }
+ if (seccomp_arch_exist(ctx, SCMP_ARCH_X86_64)) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_X86_64);
+ if (rc != 0)
+ goto out;
+ }
+ if (seccomp_arch_exist(ctx, SCMP_ARCH_X32)) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_X32);
+ if (rc != 0)
+ goto out;
+ }
+ if (seccomp_arch_exist(ctx, SCMP_ARCH_ARM)) {
+ rc = seccomp_arch_add(ctx, SCMP_ARCH_ARM);
+ if (rc != 0)
+ goto out;
+ }
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDIN_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDOUT_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, STDERR_FILENO));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ if not f.exist_arch(Arch.X86):
+ f.add_arch(Arch.X86)
+ if not f.exist_arch(Arch.X86_64):
+ f.add_arch(Arch.X86_64)
+ if not f.exist_arch(Arch.X32):
+ f.add_arch(Arch.X32)
+ if not f.exist_arch(Arch.ARM):
+ f.add_arch(Arch.ARM)
+ 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()))
+ f.add_rule(ALLOW, "close")
+ f.add_rule(ALLOW, "rt_sigreturn")
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+23-sim-arch_all_basic +all read 0 0x856B008 10 N N N ALLOW
+23-sim-arch_all_basic +all read 1-10 0x856B008 10 N N N KILL
+23-sim-arch_all_basic +all write 1-2 0x856B008 10 N N N ALLOW
+23-sim-arch_all_basic +all write 3-10 0x856B008 10 N N N KILL
+23-sim-arch_all_basic +all close N N N N N N ALLOW
+23-sim-arch_all_basic +all rt_sigreturn N N N N N N ALLOW
+23-sim-arch_all_basic +all open 0x856B008 4 N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+23-sim-arch_all_basic 50
+
+test type: bpf-valgrind
+
+# Testname
+23-sim-arch_all_basic
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ int fd;
+ scmp_filter_ctx ctx;
+ const char buf[] = "testing";
+ ssize_t buf_len = strlen(buf);
+
+ rc = util_action_parse(argv[1]);
+ if (rc != SCMP_ACT_ALLOW) {
+ rc = 1;
+ goto out;
+ }
+
+ rc = util_trap_install();
+ if (rc != 0)
+ goto out;
+
+ fd = open("/dev/null", O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd < 0) {
+ rc = errno;
+ goto out;
+ }
+
+ ctx = seccomp_init(SCMP_ACT_TRAP);
+ if (ctx == NULL)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 1,
+ SCMP_A0(SCMP_CMP_EQ, fd));
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ALLOW, SCMP_SYS(rt_sigreturn), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_rule_add_exact(ctx,
+ SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
+ if (rc != 0)
+ goto out;
+ rc = seccomp_load(ctx);
+ if (rc != 0)
+ goto out;
+
+ if (write(fd, buf, buf_len) < buf_len) {
+ rc = errno;
+ goto out;
+ }
+ if (close(fd) < 0) {
+ rc = errno;
+ goto out;
+ }
+
+ rc = 160;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import os
+import sys
+
+import util
+
+from seccomp import *
+
+def test():
+ action = util.parse_action(sys.argv[1])
+ if not action == ALLOW:
+ quit(1)
+ util.install_trap()
+
+ fd = os.open("/dev/null", os.O_WRONLY|os.O_CREAT, 0600)
+
+ f = SyscallFilter(TRAP)
+ # NOTE: additional syscalls required for python
+ f.add_rule_exactly(ALLOW, "write", Arg(0, EQ, fd))
+ f.add_rule_exactly(ALLOW, "close")
+ f.add_rule_exactly(ALLOW, "rt_sigaction")
+ f.add_rule_exactly(ALLOW, "rt_sigreturn")
+ f.add_rule_exactly(ALLOW, "exit_group")
+ f.load()
+
+ try:
+ if not os.write(fd, "testing") == len("testing"):
+ raise IOError("failed to write the full test string")
+ quit(160)
+ except OSError as ex:
+ quit(ex.errno)
+ os.close(fd)
+
+test()
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com
+#
+
+test type: live
+
+# Testname Result
+24-live-arg_allow ALLOW
--- /dev/null
+/**
+ * Seccomp Library test program
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <stdlib.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+int main(int argc, char *argv[])
+{
+ int rc;
+ struct util_options opts;
+ scmp_filter_ctx ctx;
+
+ rc = util_getopt(argc, argv, &opts);
+ if (rc < 0)
+ goto out;
+
+ ctx = seccomp_init(SCMP_ACT_KILL);
+ if (ctx == NULL)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 10, 2,
+ SCMP_A0(SCMP_CMP_EQ, 11),
+ SCMP_A1(SCMP_CMP_NE, 12));
+ if (rc != 0)
+ goto out;
+
+ rc = seccomp_rule_add_exact(ctx, SCMP_ACT_ALLOW, 20, 3,
+ SCMP_A0(SCMP_CMP_EQ, 21),
+ SCMP_A1(SCMP_CMP_NE, 22),
+ SCMP_A2(SCMP_CMP_EQ, 23));
+ if (rc != 0)
+ goto out;
+
+ rc = util_filter_output(&opts, ctx);
+ if (rc)
+ goto out;
+
+out:
+ seccomp_release(ctx);
+ return (rc < 0 ? -rc : rc);
+}
--- /dev/null
+#!/usr/bin/env python
+
+#
+# Seccomp Library test program
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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 argparse
+import sys
+
+import util
+
+from seccomp import *
+
+def test(args):
+ f = SyscallFilter(KILL)
+ f.add_rule_exactly(ALLOW, 10,
+ Arg(0, EQ, 11),
+ Arg(1, NE, 12));
+ f.add_rule_exactly(ALLOW, 20,
+ Arg(0, EQ, 21),
+ Arg(1, NE, 22),
+ Arg(2, EQ, 23));
+ return f
+
+args = util.get_opt()
+ctx = test(args)
+util.filter_output(args, ctx)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# libseccomp regression test automation data
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.com
+#
+
+test type: bpf-sim
+
+# Testname Arch Syscall Arg0 Arg1 Arg2 Arg3 Arg4 Arg5 Result
+25-sim-multilevel_chains_adv all 0-9 N N N N N N KILL
+25-sim-multilevel_chains_adv all 10 0x0000000b 0x00000000 N N N N ALLOW
+25-sim-multilevel_chains_adv x86_64 10 0x10000000b 0x00000000 N N N N KILL
+25-sim-multilevel_chains_adv x86_64 10 0x0000000b 0x10000000c N N N N ALLOW
+25-sim-multilevel_chains_adv all 11-19 N N N N N N KILL
+25-sim-multilevel_chains_adv all 20 0x00000015 0x00000000 0x00000017 N N N ALLOW
+25-sim-multilevel_chains_adv all 20 0x00000015 0x00000016 0x00000017 N N N KILL
+25-sim-multilevel_chains_adv x86_64 20 0x100000015 0x00000000 0x00000017 N N N KILL
+25-sim-multilevel_chains_adv x86_64 20 0x00000015 0x00000000 0x100000017 N N N KILL
+25-sim-multilevel_chains_adv all 21-30 N N N N N N KILL
+
+test type: bpf-sim-fuzz
+
+# Testname StressCount
+25-sim-multilevel_chains_adv 50
+
+test type: bpf-valgrind
+
+# Testname
+25-sim-multilevel_chains_adv
--- /dev/null
+#
+# Enhanced Seccomp Library Makefile
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+#
+# macros
+#
+
+include ../macros.mk
+
+#
+# configuration
+#
+
+include $(TOPDIR)/version_info.mk
+include $(TOPDIR)/configure.mk
+
+OBJS = util.o
+
+LDFLAGS := ../src/libseccomp.a $(OBJS)
+
+TEST_PRIVATE = 00-test
+
+TESTS = 01-sim-allow \
+ 02-sim-basic \
+ 03-sim-basic_chains \
+ 04-sim-multilevel_chains \
+ 05-sim-long_jumps \
+ 06-sim-actions \
+ 07-sim-db_bug_looping \
+ 08-sim-subtree_checks \
+ 09-sim-syscall_priority_pre \
+ 10-sim-syscall_priority_post \
+ 11-basic-basic_errors \
+ 12-sim-basic_masked_ops \
+ 13-basic-attrs \
+ 14-sim-reset \
+ 15-basic-resolver \
+ 16-sim-arch_basic \
+ 17-sim-arch_merge \
+ 18-sim-basic_whitelist \
+ 19-sim-missing_syscalls \
+ 20-live-basic_die \
+ 21-live-basic_allow \
+ 22-sim-basic_chains_array \
+ 23-sim-arch_all_basic \
+ 24-live-arg_allow \
+ 25-sim-multilevel_chains_adv
+
+DEPS_OBJS = $(OBJS:%.o=%.d)
+DEPS_TESTS = $(TESTS:%=%.d)
+
+#
+# targets
+#
+
+.PHONY: check clean
+
+all: $(TESTS) $(OBJS)
+
+-include $(DEPS_TESTS) $(DEPS_OBJS)
+
+$(DEPS_TESTS):
+ $(MAKEDEP_EXEC)
+ $(ADDDEP) $@ ../src/libseccomp.a
+ $(ADDDEP) $@ $(OBJS)
+
+$(TESTS):
+ $(COMPILE_EXEC)
+
+$(TEST_PRIVATE): 00-test.c $(OBJS) ../src/libseccomp.a
+ $(COMPILE_EXEC)
+
+check: $(TESTS)
+ ./regression
+
+clean:
+ $(RM) $(DEPS_TESTS) $(DEPS_OBJS) $(TESTS) $(TEST_PRIVATE) $(OBJS) *.pyc
--- /dev/null
+#!/bin/bash
+
+#
+# libseccomp regression test automation script
+#
+# Copyright IBM Corp. 2012
+# Author: Corey Bryant <coreyb@linux.vnet.ibm.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>.
+#
+
+GLBL_ARCH_SUPPORT="x86 x86_64 x32 arm"
+
+GLBL_SYS_ARCH="../tools/scmp_arch_detect"
+GLBL_SYS_RESOLVER="../tools/scmp_sys_resolver"
+GLBL_SYS_SIM="../tools/scmp_bpf_sim"
+
+####
+# functions
+
+#
+# Dependency check
+#
+# Arguments:
+# 1 Dependency to check for
+#
+function check_deps() {
+ [[ -z "$1" ]] && return
+ which "$1" >& /dev/null
+ return $?
+}
+
+#
+# Dependency verification
+#
+# Arguments:
+# 1 Dependency to check for
+#
+function verify_deps() {
+ [[ -z "$1" ]] && return
+ if ! check_deps "$1"; then
+ echo "error: install \"$1\" and include it in your \$PATH"
+ exit 1
+ fi
+}
+
+#
+# Print out script usage details
+#
+function usage() {
+cat << EOF
+usage: regression [-h] [-v] [-m MODE] [-a] [-b BATCH_NAME] [-l <LOG>]
+ [-s SINGLE_TEST] [-t <TEMP_DIR>] [-T <TEST_TYPE>]
+
+libseccomp regression test automation script
+optional arguments:
+ -h show this help message and exit
+ -m MODE specified the test mode [c (default), python]
+ -a specifies all tests are to be run
+ -b BATCH_NAME specifies batch of tests to be run
+ -l [LOG] specifies log file to write test results to
+ -s SINGLE_TEST specifies individual test number to be run
+ -t [TEMP_DIR] specifies directory to create temporary files in
+ -T [TEST_TYPE] only run tests matching the specified type
+ -v specifies that verbose output be provided
+EOF
+}
+
+#
+# Generate a string representing the test number
+#
+# Arguments:
+# 1 string containing the batch name
+# 2 value of the test number from the input test data file
+# 3 value of the subtest number that corresponds to argument 1
+#
+# The actual test number from the input test data file is 1 for the first
+# test found in the file, 2 for the second, etc.
+#
+# The subtest number is useful for batches that generate multiple tests based
+# on a single line of input from the test data file. The subtest number
+# should be set to zero if the corresponding test data is actual test data
+# that was read from the input file, and should be set to a value greater than
+# zero if the corresponding test data is generated.
+#
+function generate_test_num() {
+ local testnumstr=$(printf '%s%%%%%03d-%05d' "$1" $2 $3)
+ echo "$testnumstr"
+}
+
+#
+# Print the test data to the log file
+#
+# Arguments:
+# 1 string containing generated test number
+# 2 string containing line of test data
+#
+function print_data() {
+ if [[ -n $verbose ]]; then
+ printf "Test %s data: %s\n" "$1" "$2" >&$logfd
+ fi
+}
+
+#
+# Print the test result to the log file
+#
+# Arguments:
+# 1 string containing generated test number
+# 2 string containing the test result (INFO, SUCCESS, ERROR, or FAILURE)
+# 3 string containing addition details
+#
+function print_result() {
+ if [[ $2 == "INFO" && -z $verbose ]]; then
+ return
+ fi
+ if [[ $3 == "" ]]; then
+ printf "Test %s result: %s\n" "$1" "$2" >&$logfd
+ else
+ printf "Test %s result: %s %s\n" "$1" "$2" "$3" >&$logfd
+ fi
+}
+
+#
+# Print the valgrind header to the log file
+#
+# Arguments:
+# 1 string containing generated test number
+#
+function print_valgrind() {
+ if [[ -n $verbose ]]; then
+ printf "Test %s valgrind output\n" "$1" >&$logfd
+ fi
+}
+
+#
+# Get the low or high range value from a range specification
+#
+# Arguments:
+# 1 value specifying range value to retrieve: low (1) or high (2)
+# 2 string containing dash-separated range or a single value
+#
+function get_range() {
+ if [[ $2 =~ ^[0-9a-fA-Fx]+-[0-9a-fA-Fx]+$ ]]; then
+ # if there's a dash, get the low or high range value
+ range_val=$(echo "$2" | cut -d'-' -f "$1")
+ else
+ # otherwise there should just be a single value
+ range_val="$2"
+ fi
+ echo "$range_val"
+}
+
+#
+# Run the specified test command (with valgrind if requested)
+#
+# Arguments:
+# 1 string containing generated test number
+# 2 string containing command name
+# 3 string containing command options
+# 4 number for the stdout fd
+# 5 number for the stderr fd
+#
+function run_test_command() {
+ local cmd
+
+ if [[ $mode == "python" ]]; then
+ cmd="PYTHONPATH=$PYTHONPATH"
+ cmd="$cmd:$(cd $(pwd)/../src/python/build/lib.*; pwd)"
+ cmd="$cmd /usr/bin/env python $2.py $3"
+ else
+ cmd="$2 $3"
+ fi
+
+ # setup the stdout/stderr redirects
+ local stdout=$4
+ local stderr=$5
+ [[ -z $stdout ]] && stdout=$logfd
+ [[ -z $stderr ]] && stderr=$logfd
+
+ # run the command
+ eval "$cmd" 1>&$stdout 2>&$stderr
+
+ # return the command's return code
+ return $?
+}
+
+#
+# Generate pseudo-random string of alphanumeric characters
+#
+# The generated string will be no larger than the corresponding
+# architecture's register size.
+#
+function generate_random_data() {
+ local rcount
+ local rdata
+ if [[ $arch == "x86_64" ]]; then
+ rcount=$[ ($RANDOM % 16) + 1 ]
+ else
+ rcount=$[ ($RANDOM % 8) + 1 ]
+ fi
+ rdata=$(echo $(</dev/urandom tr -dc A-Za-z0-9 | head -c"$rcount"))
+ echo "$rdata"
+}
+
+#
+# Run the specified "bpf-sim-fuzz" test
+#
+# Tests that belong to the "bpf-sim-fuzz" test type generate a BPF filter and
+# then run a simulated system call test with pseudo-random fuzz data for the
+# syscall and argument values. Tests that belong to this test type provide the
+# following data on a single line in the input batch file:
+#
+# Testname - The executable test name (e.g. 01-allow, 02-basic, etc.)
+# StressCount - The number of fuzz tests to run against the filter
+#
+# The following test data is output to the logfile for each generated test:
+#
+# Testname - The executable test name (e.g. 01-allow, 02-basic, etc.)
+# Syscall - The fuzzed syscall value to be simulated against the filter
+# Arg0-5 - The fuzzed syscall arg values to be simulated against the filter
+#
+# Arguments:
+# 1 string containing the batch name
+# 2 value of test number from batch file
+# 3 string containing line of test data from batch file
+#
+function run_test_bpf_sim_fuzz() {
+ local rc
+
+ # begin splitting the test data from the line into individual variables
+ local line=($3)
+ local testname=${line[0]}
+ local stress_count=${line[1]}
+
+ for i in $(seq 1 $stress_count); do
+ local sys=$(generate_random_data)
+ local -a arg=($(generate_random_data) $(generate_random_data) \
+ $(generate_random_data) $(generate_random_data) \
+ $(generate_random_data) $(generate_random_data))
+
+ # get the generated sub-test num string
+ local testnumstr=$(generate_test_num "$1" $2 $i)
+
+ # set up log file test data line for this individual test,
+ # spacing is added to align the output in the correct columns
+ local -a COL_WIDTH=(26 17 17 17 17 17 17)
+ local testdata=$(printf "%-${COL_WIDTH[0]}s" $testname)
+ testdata+=$(printf "%-${COL_WIDTH[1]}s" $sys)
+ testdata+=$(printf "%-${COL_WIDTH[2]}s" ${arg[0]})
+ testdata+=$(printf "%-${COL_WIDTH[3]}s" ${arg[1]})
+ testdata+=$(printf "%-${COL_WIDTH[4]}s" ${arg[2]})
+ testdata+=$(printf "%-${COL_WIDTH[5]}s" ${arg[3]})
+ testdata+=$(printf "%-${COL_WIDTH[6]}s" ${arg[4]})
+ testdata+=$(printf "%s" ${arg[5]})
+
+ # print out the generated test data to the log file
+ print_data "$testnumstr" "$testdata"
+
+ # set up the syscall argument values to be passed to bpf_sim
+ for i in {0..5}; do
+ arg[$i]=" -$i ${arg[$i]} "
+ done
+
+ # run the test command and put the BPF filter in a temp file
+ exec 4>$tmpfile
+ run_test_command "$testnumstr" "./$testname" "-b" 4 ""
+ rc=$?
+ exec 4>&-
+ if [[ $rc -ne 0 ]]; then
+ print_result $testnumstr "ERROR" "$testname rc=$rc"
+ stats_error=$(($stats_error+1))
+ return
+ fi
+
+ # simulate the fuzzed syscall data against the BPF filter, we
+ # don't verify the resulting action since we're just testing for
+ # stability
+ allow=$($GLBL_SYS_SIM -f $tmpfile -s $sys \
+ ${arg[0]} ${arg[1]} ${arg[2]} ${arg[3]} ${arg[4]} \
+ ${arg[5]})
+ rc=$?
+ if [[ $rc -ne 0 ]]; then
+ print_result $testnumstr "ERROR" "bpf_sim rc=$rc"
+ stats_error=$(($stats_error+1))
+ else
+ print_result $testnumstr "SUCCESS" ""
+ stats_success=$(($stats_success+1))
+ fi
+ stats_all=$(($stats_all+1))
+ done
+}
+
+#
+# Run the specified "bpf-sim" test
+#
+# Tests that belong to the "bpf-sim" test type generate a BPF filter and then
+# run a simulated system call test to validate the filter. Tests that belong to
+# this test type provide the following data on a single line in the input batch
+# file:
+#
+# Testname - The executable test name (e.g. 01-allow, 02-basic, etc.)
+# Arch - The architecture that the test should be run on (all, x86, x86_64)
+# Syscall - The syscall to simulate against the generated filter
+# Arg0-5 - The syscall arguments to simulate against the generated filter
+# Result - The expected simulation result (ALLOW, KILL, etc.)
+#
+# If a range of syscall or argument values are specified (e.g. 1-9), a test is
+# generated for every combination of range values. Otherwise, the individual
+# test is run.
+#
+# Arguments:
+# 1 string containing the batch name
+# 2 value of test number from batch file
+# 3 string containing line of test data from batch file
+#
+function run_test_bpf_sim() {
+ local rc
+ local LOW=1
+ local HIGH=2
+ local -a arg_empty=(false false false false false false)
+
+ # begin splitting the test data from the line into individual variables
+ local line=($3)
+ local testname=${line[0]}
+ local testarch=${line[1]}
+ local low_syscall #line[2]
+ local high_syscall #line[2]
+ local -a low_arg #line[3-8]
+ local -a high_arg #line[3-8]
+ local result=${line[9]}
+
+ if [[ "${testarch:0:1}" == "+" ]]; then
+ # run the tests on the specified architecture(s)
+ simarch_list="${testarch:1}"
+ if [[ "$simarch_list" == "all" ]]; then
+ simarch_list="$GLBL_ARCH_SUPPORT"
+ fi
+ elif [[ "$testarch" != "all" ]] && [[ "$testarch" != "$arch" ]]; then
+ # only run tests that match the current architecture
+ print_result $(generate_test_num "$1" $2 1) "INFO" \
+ "Test skipped due to test/system architecture difference"
+ stats_skipped=$(($stats_skipped+1))
+ return
+ else
+ # run the tests on the native architecture
+ simarch_list="$arch"
+ fi
+
+ # get low and high range arg values
+ line_i=3
+ for arg_i in {0..5}; do
+ low_arg[$arg_i]=$(get_range $LOW "${line[$line_i]}")
+ high_arg[$arg_i]=$(get_range $HIGH "${line[$line_i]}")
+
+ # fix up empty arg values so the nested loops work
+ if [[ ${low_arg[$arg_i]} == "N" ]]; then
+ arg_empty[$arg_i]=true
+ low_arg[$arg_i]=0
+ high_arg[$arg_i]=0
+ fi
+
+ line_i=$(($line_i+1))
+ done
+
+ # loop through the selected architectures
+ for simarch in $simarch_list; do
+ # print architecture header if necessary
+ if [[ $simarch != $simarch_list ]]; then
+ echo " test arch: $simarch" >&$logfd
+ fi
+
+ # reset the subtest number
+ local subtestnum=1
+
+ # get low and high syscall values and convert them to numbers
+ low_syscall=$(get_range $LOW "${line[2]}")
+ if [[ ! $low_syscall =~ ^[0-9]+$ ]]; then
+ low_syscall=$($GLBL_SYS_RESOLVER -a $simarch -t \
+ $low_syscall)
+ if [[ $? -ne 0 ]]; then
+ print_result $(generate_test_num "$1" $2 1) \
+ "ERROR" "sys_resolver rc=$?"
+ stats_error=$(($stats_error+1))
+ return
+ fi
+ fi
+ high_syscall=$(get_range $HIGH "${line[2]}")
+ if [[ ! $high_syscall =~ ^[0-9]+$ ]]; then
+ high_syscall=$($GLBL_SYS_RESOLVER -a $simarch -t \
+ $high_syscall)
+ if [[ $? -ne 0 ]]; then
+ print_result $(generate_test_num "$1" $2 1) \
+ "ERROR" "sys_resolver rc=$?"
+ stats_error=$(($stats_error+1))
+ return
+ fi
+ fi
+
+ # if ranges exist, the following will loop through all syscall
+ # and arg ranges and generate/run every combination of requested
+ # tests; if no ranges were specifed, then the single test is
+ # run
+ for sys in $(seq -f "%1.0f" $low_syscall $high_syscall); do
+ for arg0 in $(seq -f "%1.0f" ${low_arg[0]} ${high_arg[0]}); do
+ for arg1 in $(seq -f "%1.0f" ${low_arg[1]} ${high_arg[1]}); do
+ for arg2 in $(seq -f "%1.0f" ${low_arg[2]} ${high_arg[2]}); do
+ for arg3 in $(seq -f "%1.0f" ${low_arg[3]} ${high_arg[3]}); do
+ for arg4 in $(seq -f "%1.0f" ${low_arg[4]} ${high_arg[4]}); do
+ for arg5 in $(seq -f "%1.0f" ${low_arg[5]} ${high_arg[5]}); do
+ local -a arg=($arg0 $arg1 $arg2 $arg3 $arg4 $arg5)
+
+ # Get the generated sub-test num string
+ local testnumstr=$(generate_test_num "$1" $2 \
+ $subtestnum)
+
+ # format any empty args to print to log file
+ for i in {0..5}; do
+ if ${arg_empty[$i]}; then
+ arg[$i]="N"
+ fi
+ done
+
+ # set up log file test data line for this
+ # individual test, spacing is added to align
+ # the output in the correct columns
+ local -a COL_WIDTH=(26 08 14 11 17 21 09 06 06)
+ local testdata=$(printf "%-${COL_WIDTH[0]}s" $testname)
+ testdata+=$(printf "%-${COL_WIDTH[1]}s" $simarch)
+ testdata+=$(printf "%-${COL_WIDTH[2]}s" $sys)
+ testdata+=$(printf "%-${COL_WIDTH[3]}s" ${arg[0]})
+ testdata+=$(printf "%-${COL_WIDTH[4]}s" ${arg[1]})
+ testdata+=$(printf "%-${COL_WIDTH[5]}s" ${arg[2]})
+ testdata+=$(printf "%-${COL_WIDTH[6]}s" ${arg[3]})
+ testdata+=$(printf "%-${COL_WIDTH[7]}s" ${arg[4]})
+ testdata+=$(printf "%-${COL_WIDTH[8]}s" ${arg[5]})
+ testdata+=$(printf "%-${COL_WIDTH[9]}s" $result)
+
+ # print out the test data to the log file
+ print_data "$testnumstr" "$testdata"
+
+ # set up the syscall arguments to be passed to bpf_sim
+ for i in {0..5}; do
+ if ${arg_empty[$i]}; then
+ arg[$i]=""
+ else
+ arg[$i]=" -$i ${arg[$i]} "
+ fi
+ done
+
+ # run the test command and put the BPF in a temp file
+ exec 4>$tmpfile
+ run_test_command "$testnumstr" "./$testname" "-b" 4 ""
+ rc=$?
+ exec 4>&-
+ if [[ $rc -ne 0 ]]; then
+ print_result $testnumstr \
+ "ERROR" "$testname rc=$rc"
+ stats_error=$(($stats_error+1))
+ return
+ fi
+
+ # simulate the specifed syscall against the BPF filter
+ # and verify the results
+ action=$($GLBL_SYS_SIM -a $simarch -f $tmpfile \
+ -s $sys ${arg[0]} ${arg[1]} ${arg[2]} \
+ ${arg[3]} ${arg[4]} ${arg[5]})
+ rc=$?
+ if [[ $rc -ne 0 ]]; then
+ print_result $testnumstr \
+ "ERROR" "bpf_sim rc=$rc"
+ stats_error=$(($stats_error+1))
+ elif [[ "$action" != "$result" ]]; then
+ print_result $testnumstr "FAILURE" \
+ "bpf_sim resulted in $action"
+ stats_failure=$(($stats_failure+1))
+ else
+ print_result $testnumstr "SUCCESS" ""
+ stats_success=$(($stats_success+1))
+ fi
+ stats_all=$(($stats_all+1))
+
+ subtestnum=$(($subtestnum+1))
+ done # syscall
+ done # arg0
+ done # arg1
+ done # arg2
+ done # arg3
+ done # arg4
+ done # arg5
+ done # architecture
+}
+
+#
+# Run the specified "basic" test
+#
+# Tests that belong to the "basic" test type will simply have the command
+# specified in the input batch file. The command must return zero for success
+# and non-zero for failure.
+#
+# Arguments:
+# 1 value of test number from batch file
+# 2 string containing line of test data from batch file
+#
+function run_test_basic() {
+ local rc
+
+ # print out the input test data to the log file
+ print_data "$1" "$2"
+
+ # run the command
+ run_test_command "$1" "./$2" "" "" ""
+ rc=$?
+ if [[ $rc -ne 0 ]]; then
+ print_result $1 "FAILURE" "$2 rc=$rc"
+ stats_failure=$(($stats_failure+1))
+ else
+ print_result $1 "SUCCESS" ""
+ stats_success=$(($stats_success+1))
+ fi
+ stats_all=$(($stats_all+1))
+}
+
+#
+# Run the specified "bpf-valgrind" test
+#
+# Tests that belong to the "bpf-valgrind" test type generate a BPF filter
+# while running under valgrind to detect any memory errors.
+#
+# Arguments:
+# 1 value of test number from batch file
+# 2 string containing line of test data from batch file
+#
+function run_test_bpf_valgrind() {
+ local rc
+ local testcmd
+
+ # we only support the native/c test mode here
+ if [[ $mode != "c" ]]; then
+ stats_skipped=$(($stats_skipped+1))
+ return
+ fi
+
+ # print out the input test data to the log file
+ print_data "$1" "$2"
+
+ # build the command
+ testcmd="$2"
+ testvalgrind="valgrind \
+ --tool=memcheck \
+ --error-exitcode=1 \
+ --leak-check=full \
+ --read-var-info=yes \
+ --track-origins=yes"
+ if [[ -n $logfile ]]; then
+ testvalgrind+=" --log-fd=$logfd"
+ fi
+ if [[ -z $verbose ]]; then
+ testvalgrind+=" --quiet --log-fd=4"
+ fi
+
+ # run the command
+ exec 4>/dev/null
+ print_valgrind "$1"
+ run_test_command "$1" "$testvalgrind --" "./$testcmd -b" 4 2
+ rc=$?
+ exec 4>&-
+ if [[ $rc -ne 0 ]]; then
+ print_result $1 "FAILURE" "$2 rc=$rc"
+ stats_failure=$(($stats_failure+1))
+ else
+ print_result $1 "SUCCESS" ""
+ stats_success=$(($stats_success+1))
+ fi
+ stats_all=$(($stats_all+1))
+}
+
+#
+# Run the specified "live" test
+#
+# Tests that belong to the "live" test type will attempt to run a live test
+# of the libseccomp library on the host system; for obvious reasons the host
+# system must support seccomp mode 2 for this to work correctly.
+#
+# Arguments:
+# 1 value of test number from batch file
+# 2 string containing line of test data from batch file
+#
+function run_test_live() {
+ local rc
+ local line=($2)
+
+ # parse the test line
+ line_cmd=${line[0]}
+ line_act=${line[1]}
+ line_test="$line_cmd $line_act"
+
+ # print out the input test data to the log file
+ print_data "$1" "$2"
+
+ # run the command
+ exec 4>/dev/null
+ run_test_command "$1" "./$line_cmd" "$line_act" "" 4
+ rc=$?
+ exec 4>&-
+
+ # return value codes for this test type:
+ # 159: KILL
+ # 160: ALLOW
+ # 161: TRAP
+ # 162: TRACE (currently unsupported)
+ # 163: ERRNO
+ if [[ $line_act == "KILL" && $rc -eq 159 ]]; then
+ print_result $1 "SUCCESS" ""
+ stats_success=$(($stats_success+1))
+ elif [[ $line_act == "ALLOW" && $rc -eq 160 ]]; then
+ print_result $1 "SUCCESS" ""
+ stats_success=$(($stats_success+1))
+ elif [[ $line_act == "TRAP" && $rc -eq 161 ]]; then
+ print_result $1 "SUCCESS" ""
+ stats_success=$(($stats_success+1))
+ elif [[ $line_act == "TRACE" ]]; then
+ print_result $1 "ERROR" "unsupported action \"$line_act\""
+ stats_error=$(($stats_error+1))
+ elif [[ $line_act == "ERRNO" && $rc -eq 163 ]]; then
+ print_result $1 "SUCCESS" ""
+ stats_success=$(($stats_success+1))
+ else
+ print_result $1 "FAILURE" "$line_test rc=$rc"
+ stats_failure=$(($stats_failure+1))
+ fi
+ stats_all=$(($stats_all+1))
+}
+
+#
+# Run a single test from the specified batch
+#
+# Arguments:
+# 1 string containing the batch name
+# 2 value of test number from batch file
+# 3 string containing line of test data from batch file
+# 4 string containing test type that this test belongs to
+#
+function run_test() {
+ # generate the test number string for the line of batch test data
+ local testnumstr=$(generate_test_num "$1" $2 1)
+
+ # ensure we only run tests which match the specified type
+ [[ -n $type && "$4" != "$type" ]] && return
+
+ # execute the function corresponding to the test type
+ if [[ "$4" == "basic" ]]; then
+ run_test_basic "$testnumstr" "$3"
+ elif [[ "$4" == "bpf-sim" ]]; then
+ run_test_bpf_sim "$1" $2 "$3"
+ elif [[ "$4" == "bpf-sim-fuzz" ]]; then
+ run_test_bpf_sim_fuzz "$1" $2 "$3"
+ elif [[ "$4" == "bpf-valgrind" ]]; then
+ # only run this test if valgrind is installed
+ if check_deps valgrind; then
+ run_test_bpf_valgrind "$testnumstr" "$3"
+ else
+ stats_skipped=$(($stats_skipped+1))
+ fi
+ elif [[ "$4" == "live" ]]; then
+ # only run this test if explicitly requested
+ if [[ -n $type ]]; then
+ run_test_live "$testnumstr" "$3"
+ else
+ stats_skipped=$(($stats_skipped+1))
+ fi
+ else
+ print_result $testnumstr "ERROR" "test type $4 not supported"
+ stats_error=$(($stats_error+1))
+ fi
+}
+
+#
+# Run the requested tests
+#
+function run_tests() {
+ # loop through all test files
+ for file in *.tests; do
+ local testnum=1
+ local batch_requested=false
+ local batch_name=""
+
+ # extract the batch name from the file name
+ batch_name=$(basename $file .tests)
+
+ # check if this batch was requested
+ if [[ ${batch_list[@]} ]]; then
+ for b in ${batch_list[@]}; do
+ if [[ $b == $batch_name ]]; then
+ batch_requested=true
+ break
+ fi
+ done
+ if ! $batch_requested; then
+ continue
+ fi
+ fi
+
+ # print a test batch header
+ echo " batch name: $batch_name" >&$logfd
+
+ # loop through each line and run the requested tests
+ while read line; do
+ # strip whitespace, comments, and blank lines
+ line=$(echo "$line" | \
+ sed -e 's/^[\t ]*//;s/[\t ]*$//;' | \
+ sed -e '/^[#].*$/d;/^$/d')
+ if [[ -z $line ]]; then
+ continue
+ fi
+
+ if [[ $line =~ ^"test type": ]]; then
+ test_type=$(echo "$line" | \
+ sed -e 's/^test type: //;')
+ # print a test mode and type header
+ echo " test mode: $mode" >&$logfd
+ echo " test type: $test_type" >&$logfd
+ continue
+ fi
+
+ if [[ ${single_list[@]} ]]; then
+ for i in ${single_list[@]}; do
+ if [ $i -eq $testnum ]; then
+ # we're running a single test
+ run_test "$batch_name" \
+ $testnum "$line" \
+ "$test_type"
+ fi
+ done
+ else
+ # we're running a test from a batch
+ run_test "$batch_name" \
+ $testnum "$line" "$test_type"
+ fi
+ testnum=$(($testnum+1))
+ done < "$file"
+ done
+}
+
+####
+# main
+
+# verify general script dependencies
+verify_deps head
+verify_deps sed
+verify_deps seq
+verify_deps tr
+
+# global variables
+declare -a batch_list
+declare -a single_list
+arch=
+batch_count=0
+logfile=
+logfd=
+mode_list=""
+runall=
+singlecount=0
+tmpfile=""
+tmpdir=""
+type=
+verbose=
+stats_all=0
+stats_skipped=0
+stats_success=0
+stats_failure=0
+stats_error=0
+
+while getopts "ab:gl:m:s:t:T:vh" opt; do
+ case $opt in
+ a)
+ runall=1
+ ;;
+ b)
+ batch_list[batch_count]="$OPTARG"
+ batch_count=$(($batch_count+1))
+ ;;
+ l)
+ logfile="$OPTARG"
+ ;;
+ m)
+ case $OPTARG in
+ c)
+ mode_list="$mode_list c"
+ ;;
+ python)
+ verify_deps python
+ mode_list="$mode_list python"
+ ;;
+ *)
+ usage
+ exit 1
+ esac
+ ;;
+ s)
+ single_list[single_count]=$OPTARG
+ single_count=$(($single_count+1))
+ ;;
+ t)
+ tmpdir="$OPTARG"
+ ;;
+ T)
+ type="$OPTARG"
+ ;;
+ v)
+ verbose=1
+ ;;
+ h|*)
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+# default to running the C tests
+if [[ -z $mode_list ]]; then
+ mode_list="c"
+fi
+
+# default to all tests if batch or single tests not requested
+if [[ -z $batch_list ]] && [[ -z $single_list ]]; then
+ runall=1
+fi
+
+# drop any requested batch and single tests if all tests were requested
+if [[ -n $runall ]]; then
+ batch_list=()
+ single_list=()
+fi
+
+# open log file for append (default to stdout)
+if [[ -n $logfile ]]; then
+ logfd=3
+ exec 3>>"$logfile"
+else
+ logfd=1
+fi
+
+# open temporary file
+if [[ -n $tmpdir ]]; then
+ tmpfile=$(mktemp -t regression_XXXXXX --tmpdir=$tmpdir)
+else
+ tmpfile=$(mktemp -t regression_XXXXXX)
+fi
+
+# determine the current system's architecture
+arch=$($GLBL_SYS_ARCH)
+
+# display the test output and run the requested tests
+echo "=============== $(date) ===============" >&$logfd
+echo "Regression Test Report (\"regression $*\")" >&$logfd
+for mode in $mode_list; do
+ run_tests
+done
+echo "Regression Test Summary" >&$logfd
+echo " tests run: $stats_all" >&$logfd
+echo " tests skipped: $stats_skipped" >&$logfd
+echo " tests passed: $stats_success" >&$logfd
+echo " tests failed: $stats_failure" >&$logfd
+echo " tests errored: $stats_error" >&$logfd
+echo "============================================================" >&$logfd
+
+# cleanup and exit
+rm -f $tmpfile
+rc=0
+[[ $stats_failure -gt 0 ]] && rc=$(($rc + 2))
+[[ $stats_error -gt 0 ]] && rc=$(($rc + 4))
+
+exit $rc
--- /dev/null
+#!/bin/bash
+
+#
+# libseccomp test diff generator
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+####
+# functions
+
+#
+# Print out script usage details
+#
+function usage() {
+cat << EOF
+usage: regression [-h] LABEL_1 LABEL_2
+
+libseccomp test diff generator script
+optional arguments:
+ -h show this help message and exit
+EOF
+}
+
+#
+# Print the test header
+#
+# Arguments:
+# 1 string containing generated test number
+#
+function print_test() {
+ printf "Test %s comparison:\n" "$1"
+}
+
+#
+# Compare the tests
+#
+# Arguments:
+# 1 string containing first test label
+# 2 string containing second test label
+#
+function diff_tests() {
+ local batch_name
+ local label_a
+ local label_b
+ local file_a
+ local file_b
+
+ if [[ -n $1 ]]; then
+ label_a=".$1"
+ else
+ label_a=""
+ fi
+
+ if [[ -n $2 ]]; then
+ label_b=".$2"
+ else
+ label_b=""
+ fi
+
+ for file in *-sim-*.tests; do
+ # extract the batch name from the file name
+ batch_name=$(basename $file .tests)
+
+ print_test "$batch_name"
+
+ file_a="${batch_name}${label_a}"
+ file_b="${batch_name}${label_b}"
+
+ if [[ -r "$file_a.pfc" && -r "$file_b.pfc" ]]; then
+ diff -pu "$file_a.pfc" "$file_b.pfc"
+ fi
+
+ if [[ -r "$file_a.bpf" && -r "$file_b.bpf" ]]; then
+ diff -pu "$file_a.bpf" "$file_b.bpf"
+ fi
+
+ if [[ -r "$file_a.bpfd" && -r "$file_b.bpfd" ]]; then
+ diff -pu "$file_a.bpfd" "$file_b.bpfd"
+ fi
+ done
+
+ return
+}
+
+####
+# main
+
+opt_label=
+opt_disasm=0
+
+while getopts "h" opt; do
+ case $opt in
+ h|*)
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+stats_all=0
+stats_failure=0
+
+# display the test output and run the requested tests
+echo "=============== $(date) ==============="
+echo "Comparing Test Output (\"testdiff $*\")"
+diff_tests "$1" "$2"
+echo "============================================================"
+
+# exit
+exit 0
--- /dev/null
+#!/bin/bash
+
+#
+# libseccomp test output generator
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+####
+# functions
+
+#
+# Dependency verification
+#
+# Arguments:
+# 1 Dependency to check for
+#
+function verify_deps() {
+ [[ -z "$1" ]] && return
+ if ! which "$1" >& /dev/null; then
+ echo "error: install \"$1\" and include it in your \$PATH"
+ exit 1
+ fi
+}
+
+#
+# Print out script usage details
+#
+function usage() {
+cat << EOF
+usage: regression [-h] [-d] [-l LABEL]
+
+libseccomp test output generator script
+optional arguments:
+ -h show this help message and exit
+ -b generate BPF output
+ -d generate disassembled BPF output
+ -p generate PFC output
+ -v perform valgrind checks
+ -l [LABEL] specifies label for the test output
+EOF
+}
+
+#
+# Print the test result
+#
+# Arguments:
+# 1 string containing generated test number
+# 2 string containing the test result
+#
+function print_result() {
+ printf "Test %s result: %s\n" "$1" "$2"
+}
+
+#
+# Run the tests
+#
+# Arguments:
+# 1 string containing output label
+#
+function run_tests() {
+ local batch_name
+ local label
+ local rc
+
+ if [[ -n $1 ]]; then
+ label=".$1"
+ else
+ label=""
+ fi
+
+ for file in *-sim-*.tests; do
+ # extract the batch name from the file name
+ batch_name=$(basename $file .tests)
+
+ if [[ -x "$batch_name" ]]; then
+ if [[ $opt_pfc -eq 1 ]]; then
+ ./$batch_name > ${batch_name}${label}.pfc
+ rc=$?
+ stats_all=$(($stats_all + 1))
+ if [[ $rc -eq 0 ]]; then
+ print_result "$batch_name [pfc]" "SUCCESS"
+ else
+ stats_failure=$(($stats_failure + 1))
+ print_result "$batch_name [pfc]" "FAILURE"
+ fi
+ fi
+
+ if [[ $opt_bpf -eq 1 ]]; then
+ ./$batch_name -b > ${batch_name}${label}.bpf
+ rc=$?
+ stats_all=$(($stats_all + 1))
+ if [[ $rc -eq 0 ]]; then
+ print_result "$batch_name [bpf]" "SUCCESS"
+ else
+ stats_failure=$(($stats_failure + 1))
+ print_result "$batch_name [bpf]" "FAILURE"
+ fi
+ fi
+
+ if [[ $opt_disasm -eq 1 ]]; then
+ ./$batch_name -b | \
+ ../tools/scmp_bpf_disasm > ${batch_name}${label}.bpfd
+ rc=$?
+ stats_all=$(($stats_all + 1))
+ if [[ $rc -eq 0 ]]; then
+ print_result "$batch_name [bpfd]" "SUCCESS"
+ else
+ stats_failure=$(($stats_failure + 1))
+ print_result "$batch_name [bpfd]" "FAILURE"
+ fi
+ fi
+
+ if [[ $opt_valgrind -eq 1 ]]; then
+ valgrind --tool=memcheck \
+ --quiet --error-exitcode=1 \
+ --leak-check=full \
+ --read-var-info=yes \
+ --track-origins=yes \
+ -- ./$batch_name -b > /dev/null
+ rc=$?
+ stats_all=$(($stats_all + 1))
+ if [[ $rc -eq 0 ]]; then
+ print_result "$batch_name [valgrind]" "SUCCESS"
+ else
+ stats_failure=$(($stats_failure + 1))
+ print_result "$batch_name [valgrind]" "FAILURE"
+ fi
+ fi
+ else
+ stats_failure=$(($stats_failure + 1))
+ print_result "$batch_name" "FAILURE"
+ fi
+ done
+
+ return
+}
+
+####
+# main
+
+opt_label=
+opt_bpf=0
+opt_disasm=0
+opt_pfc=0
+opt_valgrind=0
+
+while getopts "bphdl:v" opt; do
+ case $opt in
+ b)
+ opt_bpf=1
+ ;;
+ d)
+ opt_disasm=1
+ ;;
+ l)
+ opt_label="$OPTARG"
+ ;;
+ p)
+ opt_pfc=1
+ ;;
+ v)
+ opt_valgrind=1
+ ;;
+ h|*)
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+# verify valgrind
+[[ $opt_valgrind -eq 1 ]] && verify_deps valgrind
+
+stats_all=0
+stats_failure=0
+
+# display the test output and run the requested tests
+echo "=============== $(date) ==============="
+echo "Collecting Test Output (\"testgen $*\")"
+run_tests "$opt_label"
+echo "Test Summary"
+echo " tests run: $stats_all"
+echo " tests failed: $stats_failure"
+echo "============================================================"
+
+# cleanup and exit
+rc=0
+[[ $stats_failure -gt 0 ]] && rc=$(($rc + 2))
+
+exit $rc
--- /dev/null
+/**
+ * Seccomp Library utility code for tests
+ *
+ * Copyright (c) 2012 Red Hat <eparis@redhat.com>
+ * Author: Eric Paris <eparis@redhat.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>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <seccomp.h>
+
+#include "util.h"
+
+/**
+ * SIGSYS signal handler
+ * @param nr the signal number
+ * @param info siginfo_t pointer
+ * @param void_context handler context
+ *
+ * Simple signal handler for SIGSYS which exits with error code 161.
+ *
+ */
+static void _trap_handler(int signal, siginfo_t *info, void *ctx)
+{
+ _exit(161);
+}
+
+/**
+ * Parse the arguments passed to main
+ * @param argc the argument count
+ * @param argv the argument pointer
+ * @param opts the options structure
+ *
+ * This function parses the arguments passed to the test from the command line.
+ * Returns zero on success and negative values on failure.
+ *
+ */
+int util_getopt(int argc, char *argv[], struct util_options *opts)
+{
+ int rc = 0;
+
+ if (opts == NULL)
+ return -EFAULT;
+
+ memset(opts, 0, sizeof(*opts));
+ while (1) {
+ int c, option_index = 0;
+ const struct option long_options[] = {
+ {"bpf", no_argument, &(opts->bpf_flg), 1},
+ {"pfc", no_argument, &(opts->bpf_flg), 0},
+ {0, 0, 0, 0},
+ };
+
+ c = getopt_long(argc, argv, "bp",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 0:
+ break;
+ case 'b':
+ opts->bpf_flg = 1;
+ break;
+ case 'p':
+ opts->bpf_flg = 0;
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
+ }
+
+ if (rc == -EINVAL || optind < argc) {
+ fprintf(stderr, "usage %s: [--bpf,-b] [--pfc,-p]\n", argv[0]);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+/**
+ * Output the filter in either BPF or PFC
+ * @param opts the options structure
+ * @param ctx the filter context
+ *
+ * This function outputs the seccomp filter to stdout in either BPF or PFC
+ * format depending on the test paramaeters supplied by @opts.
+ *
+ */
+int util_filter_output(const struct util_options *opts,
+ const scmp_filter_ctx ctx)
+{
+ int rc;
+
+ if (opts == NULL)
+ return -EFAULT;
+
+ if (opts->bpf_flg)
+ rc = seccomp_export_bpf(ctx, STDOUT_FILENO);
+ else
+ rc = seccomp_export_pfc(ctx, STDOUT_FILENO);
+
+ return rc;
+}
+
+/**
+ * Install a TRAP action signal handler
+ *
+ * This function installs the TRAP action signal handler and is based on
+ * examples from Will Drewry and Kees Cook. Returns zero on success, negative
+ * values on failure.
+ *
+ */
+int util_trap_install(void)
+{
+ struct sigaction signal_handler;
+ sigset_t signal_mask;
+
+ memset(&signal_handler, 0, sizeof(signal_handler));
+ sigemptyset(&signal_mask);
+ sigaddset(&signal_mask, SIGSYS);
+
+ signal_handler.sa_sigaction = &_trap_handler;
+ signal_handler.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGSYS, &signal_handler, NULL) < 0)
+ return -errno;
+ if (sigprocmask(SIG_UNBLOCK, &signal_mask, NULL))
+ return -errno;
+
+ return 0;
+}
+
+/**
+ * Parse a filter action string into an action value
+ * @param action the action string
+ *
+ * Parse a seccomp action string into the associated integer value. Returns
+ * the correct value on success, -1 on failure.
+ *
+ */
+int util_action_parse(const char *action)
+{
+ if (action == NULL)
+ return -1;
+
+ if (strcasecmp(action, "KILL") == 0)
+ return SCMP_ACT_KILL;
+ else if (strcasecmp(action, "TRAP") == 0)
+ return SCMP_ACT_TRAP;
+ else if (strcasecmp(action, "ERRNO") == 0)
+ return SCMP_ACT_ERRNO(163);
+ else if (strcasecmp(action, "TRACE") == 0)
+ return -1; /* not yet supported */
+ else if (strcasecmp(action, "ALLOW") == 0)
+ return SCMP_ACT_ALLOW;
+
+ return -1;
+}
+
+/**
+ * Write a string to a file
+ * @param path the file path
+ *
+ * Open the specified file, write a string to the file, and close the file.
+ * Return zero on success, negative values on error.
+ *
+ */
+int util_file_write(const char *path)
+{
+ int fd;
+ const char buf[] = "testing";
+ ssize_t buf_len = strlen(buf);
+
+ fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd < 0)
+ return errno;
+ if (write(fd, buf, buf_len) < buf_len) {
+ int rc = errno;
+ close(fd);
+ return rc;
+ }
+ if (close(fd) < 0)
+ return errno;
+
+ return 0;
+}
--- /dev/null
+/**
+ * Seccomp Library utility code for tests
+ *
+ * Copyright IBM Corp. 2012
+ * Author: Corey Bryant <coreyb@linux.vnet.ibm.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>.
+ */
+
+#ifndef _UTIL_TEST_H
+#define _UTIL_TEST_H
+
+struct util_options {
+ int bpf_flg;
+};
+
+int util_getopt(int argc, char *argv[], struct util_options *opts);
+
+int util_filter_output(const struct util_options *opts,
+ const scmp_filter_ctx ctx);
+
+int util_trap_install(void);
+
+int util_action_parse(const char *action);
+
+int util_file_write(const char *path);
+
+#endif
--- /dev/null
+#
+# Seccomp Library utility code for tests
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+""" Python utility code for the libseccomp test suite """
+
+import argparse
+import os
+import sys
+import signal
+
+from seccomp import *
+
+def trap_handler(signum, frame):
+ """ SIGSYS signal handler, internal use only
+ """
+ os._exit(161)
+
+def get_opt():
+ """ Parse the arguments passed to main
+
+ Description:
+ Parse the arguments passed to the test from the command line. Returns
+ a parsed argparse object.
+ """
+ parser = argparse.ArgumentParser()
+ parser.add_argument("-b", "--bpf", action="store_true")
+ parser.add_argument("-p", "--pfc", action="store_true")
+ return parser.parse_args()
+
+def filter_output(args, ctx):
+ """ Output the filter in either BPF or PFC
+
+ Arguments:
+ args - an argparse object from UtilGetOpt()
+ ctx - a seccomp SyscallFilter object
+
+ Description:
+ Output the SyscallFilter to stdout in either BPF or PFC format depending
+ on the test's command line arguments.
+ """
+ if (args.bpf):
+ ctx.export_bpf(sys.stdout)
+ else:
+ ctx.export_pfc(sys.stdout)
+
+def install_trap():
+ """ Install a TRAP action signal handler
+
+ Description:
+ Install the TRAP action signal handler.
+ """
+ signal.signal(signal.SIGSYS, trap_handler)
+
+def parse_action(action):
+ """ Parse a filter action string into an action value
+
+ Arguments:
+ action - the action string
+
+ Description:
+ Parse a seccomp action string into the associated integer value.
+ """
+ if action == "KILL":
+ return KILL
+ elif action == "TRAP":
+ return TRAP
+ elif action == "ERRNO":
+ return ERRNO(163)
+ elif action == "TRACE":
+ raise RuntimeError("the TRACE action is not currently supported")
+ elif action == "ALLOW":
+ return ALLOW
+ raise RuntimeError("invalid action string")
+
+
+def write_file(path):
+ """ Write a string to a file
+
+ Arguments:
+ path - the file path
+
+ Description:
+ Open the specified file, write a string to the file, and close the file.
+ """
+ fd = os.open(path, os.O_WRONLY|os.O_CREAT, 0600)
+ if not os.write(fd, "testing") == len("testing"):
+ raise IOError("failed to write the full test string in write_file()")
+ os.close(fd)
+
+# kate: syntax python;
+# kate: indent-mode python; space-indent on; indent-width 4; mixedindent off;
--- /dev/null
+#
+# Enhanced Seccomp Library Makefile
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+#
+# macros
+#
+
+include ../macros.mk
+
+#
+# configuration
+#
+
+include $(TOPDIR)/configure.mk
+include $(TOPDIR)/install.mk
+
+LDFLAGS := ../src/libseccomp.a
+
+TOOLS = scmp_bpf_disasm \
+ scmp_bpf_sim \
+ scmp_sys_resolver \
+ scmp_arch_detect
+
+TOOLS_INSTALL = scmp_sys_resolver
+
+DEPS = $(TOOLS:%=%.d)
+
+#
+# targets
+#
+
+.PHONY: install clean
+
+all: $(TOOLS)
+
+-include $(DEPS)
+
+$(DEPS):
+ $(MAKEDEP_EXEC)
+
+$(TOOLS):
+ $(COMPILE_EXEC)
+
+install: $(TOOLS_INSTALL)
+ $(INSTALL_BIN_MACRO)
+
+clean:
+ $(RM) $(DEPS) $(TOOLS)
--- /dev/null
+/**
+ * BPF Language Definitions
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#ifndef _BPF_H
+#define _BPF_H
+
+#include <inttypes.h>
+#include <stddef.h>
+
+/* most of these structures and values are designed to match the Linux Kernel's
+ * BPF interface (see /usr/include/linux/{filter,seccomp}.h), but we define our
+ * own here so that we can function independent of the host OS */
+
+/* XXX - need to verify these values */
+#define BPF_SCRATCH_SIZE 6
+
+/**
+ * Syscall record data format used by seccomp
+ */
+#define BPF_SYS_ARG_MAX 6
+struct seccomp_data {
+ int32_t nr;
+ uint32_t arch;
+ uint64_t instruction_pointer;
+ uint64_t args[BPF_SYS_ARG_MAX];
+};
+#define BPF_SYSCALL_MAX (sizeof(struct seccomp_data))
+
+/**
+ * BPF instruction format
+ */
+struct sock_filter {
+ uint16_t code;
+ uint8_t jt;
+ uint8_t jf;
+ uint32_t k;
+} __attribute__ ((packed));
+typedef struct sock_filter bpf_instr_raw;
+
+/* seccomp return masks */
+#define SECCOMP_RET_ACTION 0x7fff0000U
+#define SECCOMP_RET_DATA 0x0000ffffU
+
+/* seccomp action values */
+#define SECCOMP_RET_KILL 0x00000000U
+#define SECCOMP_RET_TRAP 0x00030000U
+#define SECCOMP_RET_ERRNO 0x00050000U
+#define SECCOMP_RET_TRACE 0x7ff00000U
+#define SECCOMP_RET_ALLOW 0x7fff0000U
+
+/* bpf command classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* BPF_LD and BPF_LDX */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+#define BPF_OP(code) ((code) & 0xf0)
+/* BPF_ALU */
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+/* BPF_JMP */
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* BPF_RET (BPF_K and BPF_X also apply) */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+
+/* BPF_MISC */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+#define BPF_TXA 0x80
+
+#endif
--- /dev/null
+#!/bin/bash
+
+#
+# libseccomp code syntax checking tool
+#
+# Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+CHK_C_LIST="include/seccomp.h.in \
+ src/*.c src/*.h \
+ tests/*.c tests/*.h \
+ tools/*.c tools/*.h"
+CHK_C_EXCLUDE=""
+
+####
+# functions
+
+#
+# Dependency verification
+#
+# Arguments:
+# 1 Dependency to check for
+#
+function verify_deps() {
+ [[ -z "$1" ]] && return
+ if ! which "$1" >& /dev/null; then
+ echo "error: install \"$1\" and include it in your \$PATH"
+ exit 1
+ fi
+}
+
+#
+# Print out script usage details
+#
+function usage() {
+cat << EOF
+usage: check-syntax [-h]
+
+libseccomp code syntax checking tool
+optional arguments:
+ -h show this help message and exit
+EOF
+}
+
+#
+# Check the formatting on a C source/header file
+#
+# Arguments:
+# 1 File to check
+#
+function tool_c_style() {
+ [[ -z "$1" || ! -r "$1" ]] && return
+
+ astyle --options=none --lineend=linux --mode=c \
+ --style=linux \
+ --indent=force-tab=8 \
+ --indent-preprocessor \
+ --indent-col1-comments \
+ --min-conditional-indent=0 \
+ --max-instatement-indent=80 \
+ --pad-oper \
+ --align-pointer=name \
+ --align-reference=name \
+ --max-code-length=80 \
+ --break-after-logical < "$1" \
+ | diff -pu --label="$1" "$1" --label="$1 [CORRECTED]" -
+}
+
+#
+# Perform all known syntax checks for the configured C sources/headers
+#
+function check_c() {
+ for i in $CHK_C_LIST; do
+ echo "$CHK_C_EXCLUDE" | grep -q "$i" && continue
+ echo "Differences for $i"
+ tool_c_style "$i"
+ done
+}
+
+####
+# main
+
+verify_deps astyle
+
+while getopts "h" opt; do
+ case $opt in
+ h|*)
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+# display the results
+echo "=============== $(date) ==============="
+echo "Code Syntax Check Results (\"check-syntax $*\")"
+check_c
+echo "============================================================"
+
+# exit
+exit 0
--- /dev/null
+#!/bin/bash
+
+#
+# Runtime syscall inspector
+#
+# Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+# Author: Paul Moore <pmoore@redhat.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>.
+#
+
+####
+# functions
+
+function verify_deps() {
+ [[ -z "$1" ]] && return
+ if ! which "$1" >& /dev/null; then
+ echo "error: install \"$1\" and include it in your \$PATH"
+ exit 1
+ fi
+}
+
+####
+# main
+
+# verify script dependencies
+verify_deps strace
+verify_deps sed
+verify_deps sort
+verify_deps uniq
+
+# get the command line arguments
+opt_freq=0
+opt_args=0
+opt_out="/proc/self/fd/1"
+while getopts "afo:h" opt; do
+ case $opt in
+ a)
+ opt_args=1
+ ;;
+ f)
+ opt_freq=1
+ ;;
+ o)
+ opt_out="$OPTARG"
+ ;;
+ h|*)
+ echo "usage $0 [-f] [-a] [-o <file>] <command> [<args>]"
+ exit 1
+ esac
+done
+shift $(expr $OPTIND - 1)
+
+# generate a temporary output file
+raw=$(mktemp -t strace-raw_XXXXXX)
+out="$raw-out"
+
+# capture the strace output
+strace -o $raw -- $*
+
+# filter the raw strace
+if [[ $opt_args -eq 0 ]]; then
+ if [[ $opt_freq -eq 0 ]]; then
+ cat $raw | sed -e 's/(.*//' | sort -u > $out
+ else
+ cat $raw | sed -e 's/(.*//' | sort | uniq -c | sort -nr > $out
+ fi
+else
+ if [[ $opt_freq -eq 0 ]]; then
+ cat $raw | sed -e 's/)[ \t]*=.*$/)/' \
+ | sed -e 's/".*,/"...",/g;s/\/\*.*\*\//.../g' \
+ | sed -e 's/0x[a-f0-9]\+/.../g' \
+ | sort -u > $out
+ else
+ cat $raw | sed -e 's/)[ \t]*=.*$/)/' \
+ | sed -e 's/".*,/"...",/g;s/\/\*.*\*\//.../g' \
+ | sed -e 's/0x[a-f0-9]\+/.../g' \
+ | sort | uniq -c | sort -nr > $out
+ fi
+fi
+
+# display the output
+echo "============================================================" > $opt_out
+echo "Syscall Report (\"$*\")" >> $opt_out
+[[ $opt_freq -eq 1 ]] && echo " freq syscall" >> $opt_out
+echo "============================================================" >> $opt_out
+cat $out >> $opt_out
+
+# cleanup and exit
+rm -f $raw $out
+exit 0
--- /dev/null
+/**
+ * Architecture Detector
+ *
+ * Copyright (c) 2013 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <seccomp.h>
+
+/**
+ * Print the usage information to stderr and exit
+ * @param program the name of the current program being invoked
+ *
+ * Print the usage information and exit with EINVAL.
+ *
+ */
+static void exit_usage(const char *program)
+{
+ fprintf(stderr,
+ "usage: %s [-h] [-t]\n",
+ program);
+ exit(EINVAL);
+}
+
+/**
+ * main
+ */
+int main(int argc, char *argv[])
+{
+ int opt;
+ int token = 0;
+ uint32_t arch;
+
+ /* parse the command line */
+ while ((opt = getopt(argc, argv, "ht")) > 0) {
+ switch (opt) {
+ case 't':
+ token = 1;
+ break;
+ case 'h':
+ default:
+ /* usage information */
+ exit_usage(argv[0]);
+ }
+ }
+
+ arch = seccomp_arch_native();
+ if (token == 0) {
+ switch (arch) {
+ case SCMP_ARCH_X86:
+ printf("x86\n");
+ break;
+ case SCMP_ARCH_X86_64:
+ printf("x86_64\n");
+ break;
+ case SCMP_ARCH_X32:
+ printf("x32\n");
+ break;
+ case SCMP_ARCH_ARM:
+ printf("arm\n");
+ break;
+ default:
+ printf("unknown\n");
+ }
+ } else
+ printf("%d\n", arch);
+
+ return 0;
+}
--- /dev/null
+/**
+ * BPF Disassembler
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "bpf.h"
+
+#define _OP_FMT "%-3s"
+
+/**
+ * Decode the BPF operand
+ * @param bpf the BPF instruction
+ *
+ * Decode the BPF operand and print it to stdout.
+ *
+ */
+static void bpf_decode_op(const bpf_instr_raw *bpf)
+{
+ switch (bpf->code) {
+ case BPF_LD+BPF_W+BPF_IMM:
+ case BPF_LD+BPF_W+BPF_ABS:
+ case BPF_LD+BPF_W+BPF_IND:
+ case BPF_LD+BPF_W+BPF_MEM:
+ case BPF_LD+BPF_W+BPF_LEN:
+ case BPF_LD+BPF_W+BPF_MSH:
+ printf(_OP_FMT, "ld");
+ break;
+ case BPF_LD+BPF_H+BPF_IMM:
+ case BPF_LD+BPF_H+BPF_ABS:
+ case BPF_LD+BPF_H+BPF_IND:
+ case BPF_LD+BPF_H+BPF_MEM:
+ case BPF_LD+BPF_H+BPF_LEN:
+ case BPF_LD+BPF_H+BPF_MSH:
+ printf(_OP_FMT, "ldh");
+ break;
+ case BPF_LD+BPF_B+BPF_IMM:
+ case BPF_LD+BPF_B+BPF_ABS:
+ case BPF_LD+BPF_B+BPF_IND:
+ case BPF_LD+BPF_B+BPF_MEM:
+ case BPF_LD+BPF_B+BPF_LEN:
+ case BPF_LD+BPF_B+BPF_MSH:
+ printf(_OP_FMT, "ldb");
+ break;
+ case BPF_LDX+BPF_W+BPF_IMM:
+ case BPF_LDX+BPF_W+BPF_ABS:
+ case BPF_LDX+BPF_W+BPF_IND:
+ case BPF_LDX+BPF_W+BPF_MEM:
+ case BPF_LDX+BPF_W+BPF_LEN:
+ case BPF_LDX+BPF_W+BPF_MSH:
+ case BPF_LDX+BPF_H+BPF_IMM:
+ case BPF_LDX+BPF_H+BPF_ABS:
+ case BPF_LDX+BPF_H+BPF_IND:
+ case BPF_LDX+BPF_H+BPF_MEM:
+ case BPF_LDX+BPF_H+BPF_LEN:
+ case BPF_LDX+BPF_H+BPF_MSH:
+ case BPF_LDX+BPF_B+BPF_IMM:
+ case BPF_LDX+BPF_B+BPF_ABS:
+ case BPF_LDX+BPF_B+BPF_IND:
+ case BPF_LDX+BPF_B+BPF_MEM:
+ case BPF_LDX+BPF_B+BPF_LEN:
+ case BPF_LDX+BPF_B+BPF_MSH:
+ printf(_OP_FMT, "ldx");
+ break;
+ case BPF_ST:
+ printf(_OP_FMT, "st");
+ break;
+ case BPF_STX:
+ printf(_OP_FMT, "stx");
+ break;
+ case BPF_ALU+BPF_ADD+BPF_K:
+ case BPF_ALU+BPF_ADD+BPF_X:
+ printf(_OP_FMT, "add");
+ break;
+ case BPF_ALU+BPF_SUB+BPF_K:
+ case BPF_ALU+BPF_SUB+BPF_X:
+ printf(_OP_FMT, "sub");
+ break;
+ case BPF_ALU+BPF_MUL+BPF_K:
+ case BPF_ALU+BPF_MUL+BPF_X:
+ printf(_OP_FMT, "mul");
+ break;
+ case BPF_ALU+BPF_DIV+BPF_K:
+ case BPF_ALU+BPF_DIV+BPF_X:
+ printf(_OP_FMT, "div");
+ break;
+ case BPF_ALU+BPF_OR+BPF_K:
+ case BPF_ALU+BPF_OR+BPF_X:
+ printf(_OP_FMT, "or");
+ break;
+ case BPF_ALU+BPF_AND+BPF_K:
+ case BPF_ALU+BPF_AND+BPF_X:
+ printf(_OP_FMT, "and");
+ break;
+ case BPF_ALU+BPF_LSH+BPF_K:
+ case BPF_ALU+BPF_LSH+BPF_X:
+ printf(_OP_FMT, "lsh");
+ break;
+ case BPF_ALU+BPF_RSH+BPF_K:
+ case BPF_ALU+BPF_RSH+BPF_X:
+ printf(_OP_FMT, "rsh");
+ break;
+ case BPF_ALU+BPF_NEG+BPF_K:
+ case BPF_ALU+BPF_NEG+BPF_X:
+ printf(_OP_FMT, "neg");
+ break;
+ case BPF_JMP+BPF_JA+BPF_K:
+ case BPF_JMP+BPF_JA+BPF_X:
+ printf(_OP_FMT, "jmp");
+ break;
+ case BPF_JMP+BPF_JEQ+BPF_K:
+ case BPF_JMP+BPF_JEQ+BPF_X:
+ printf(_OP_FMT, "jeq");
+ break;
+ case BPF_JMP+BPF_JGT+BPF_K:
+ case BPF_JMP+BPF_JGT+BPF_X:
+ printf(_OP_FMT, "jgt");
+ break;
+ case BPF_JMP+BPF_JGE+BPF_K:
+ case BPF_JMP+BPF_JGE+BPF_X:
+ printf(_OP_FMT, "jge");
+ break;
+ case BPF_JMP+BPF_JSET+BPF_K:
+ case BPF_JMP+BPF_JSET+BPF_X:
+ printf(_OP_FMT, "jset");
+ break;
+ case BPF_RET+BPF_K:
+ case BPF_RET+BPF_X:
+ case BPF_RET+BPF_A:
+ printf(_OP_FMT, "ret");
+ break;
+ case BPF_MISC+BPF_TAX:
+ printf(_OP_FMT, "tax");
+ break;
+ case BPF_MISC+BPF_TXA:
+ printf(_OP_FMT, "txa");
+ break;
+ default:
+ printf(_OP_FMT, "???");
+ }
+}
+
+/**
+ * Decode the BPF arguments (JT, JF, and K)
+ * @param bpf the BPF instruction
+ * @param line the current line number
+ *
+ * Decode the BPF arguments (JT, JF, and K) and print the relevant information
+ * to stdout based on the operand.
+ *
+ */
+static void bpf_decode_args(const bpf_instr_raw *bpf, unsigned int line)
+{
+ switch (BPF_CLASS(bpf->code)) {
+ case BPF_LD:
+ case BPF_LDX:
+ switch (BPF_MODE(bpf->code)) {
+ case BPF_ABS:
+ printf("$data[%u]", bpf->k);
+ break;
+ case BPF_MEM:
+ printf("$temp[%u]", bpf->k);
+ break;
+ }
+ break;
+ case BPF_ST:
+ case BPF_STX:
+ printf("$temp[%u]", bpf->k);
+ break;
+ case BPF_ALU:
+ if (BPF_SRC(bpf->code) == BPF_K) {
+ switch (BPF_OP(bpf->code)) {
+ case BPF_OR:
+ case BPF_AND:
+ printf("0x%.8x", bpf->k);
+ break;
+ default:
+ printf("%u", bpf->k);
+ }
+ } else
+ printf("%u", bpf->k);
+ break;
+ case BPF_JMP:
+ if (BPF_OP(bpf->code) == BPF_JA) {
+ printf("%.4u", (line + 1) + bpf->k);
+ } else {
+ printf("%-4u true:%.4u false:%.4u",
+ bpf->k,
+ (line + 1) + bpf->jt,
+ (line + 1) + bpf->jf);
+ }
+ break;
+ case BPF_RET:
+ if (BPF_RVAL(bpf->code) == BPF_A) {
+ /* XXX - accumulator? */
+ printf("$acc");
+ } else if (BPF_SRC(bpf->code) == BPF_K) {
+ uint32_t act = bpf->k & SECCOMP_RET_ACTION;
+ uint32_t data = bpf->k & SECCOMP_RET_DATA;
+
+ switch (act) {
+ case SECCOMP_RET_KILL:
+ printf("KILL");
+ break;
+ case SECCOMP_RET_TRAP:
+ printf("TRAP");
+ break;
+ case SECCOMP_RET_ERRNO:
+ printf("ERRNO(%u)", data);
+ break;
+ case SECCOMP_RET_TRACE:
+ printf("TRACE(%u)", data);
+ break;
+ case SECCOMP_RET_ALLOW:
+ printf("ALLOW");
+ break;
+ default:
+ printf("0x%.8x", bpf->k);
+ }
+ } else if (BPF_SRC(bpf->code) == BPF_X) {
+ /* XXX - any idea? */
+ printf("???");
+ }
+ break;
+ case BPF_MISC:
+ break;
+ default:
+ printf("???");
+ }
+}
+
+/**
+ * Perform a simple decoding of the BPF program
+ * @param file the BPF program
+ *
+ * Read the BPF program and display the instructions. Returns zero on success,
+ * negative values on failure.
+ *
+ */
+static int bpf_decode(FILE *file)
+{
+ unsigned int line = 0;
+ size_t len;
+ bpf_instr_raw bpf;
+
+ /* header */
+ printf(" line OP JT JF K\n");
+ printf("=================================\n");
+
+ while ((len = fread(&bpf, sizeof(bpf), 1, file))) {
+ printf(" %.4u: 0x%.2x 0x%.2x 0x%.2x 0x%.8x",
+ line, bpf.code, bpf.jt, bpf.jf, bpf.k);
+
+ printf(" ");
+ bpf_decode_op(&bpf);
+ printf(" ");
+ bpf_decode_args(&bpf, line);
+ printf("\n");
+
+ line++;
+ }
+
+ if (ferror(file))
+ return errno;
+ return 0;
+}
+
+/**
+ * main
+ */
+int main(int argc, char *argv[])
+{
+ int rc;
+ FILE *file;
+
+ if (argc > 2) {
+ fprintf(stderr, "usage: %s [<bpf_file>]\n", argv[0]);
+ return EINVAL;
+ }
+
+ if (argc == 2) {
+ file = fopen(argv[1], "r");
+ if (file == NULL) {
+ fprintf(stderr, "error: unable to open \"%s\" (%s)\n",
+ argv[1], strerror(errno));
+ return errno;
+ }
+ } else
+ file = stdin;
+
+ rc = bpf_decode(file);
+ fclose(file);
+
+ return rc;
+}
+
--- /dev/null
+/**
+ * BPF Simulator
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <elf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/audit.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "bpf.h"
+
+#define BPF_PRG_MAX_LEN 4096
+
+/**
+ * BPF simulator machine state
+ */
+struct sim_state {
+ uint32_t acc;
+ uint32_t temp[BPF_SCRATCH_SIZE];
+};
+
+struct bpf_program {
+ size_t i_cnt;
+ bpf_instr_raw *i;
+};
+
+static unsigned int opt_verbose = 0;
+
+/**
+ * Print the usage information to stderr and exit
+ * @param program the name of the current program being invoked
+ *
+ * Print the usage information and exit with EINVAL.
+ *
+ */
+static void exit_usage(const char *program)
+{
+ fprintf(stderr,
+ "usage: %s -f <bpf_file> [-v]"
+ " -a <arch> -s <syscall_num> [-0 <a0>] ... [-5 <a5>]\n",
+ program);
+ exit(EINVAL);
+}
+
+/**
+ * Handle a simulator fault
+ * @param rc the error or return code
+ *
+ * Print a "FAULT" to stderr to indicate a simulator fault, and an errno value
+ * if the simulator is running in verbose mode, then exit with EFAULT.
+ *
+ */
+static void exit_fault(unsigned int rc)
+{
+ if (opt_verbose)
+ fprintf(stderr, "FAULT: errno = %d\n", rc);
+ else
+ fprintf(stderr, "FAULT\n");
+ exit(EFAULT);
+}
+
+/**
+ * Handle a BPF program error
+ * @param rc the error or return code
+ * @param line the line number
+ *
+ * Print an "ERROR" to stderr to indicate a program error, and an errno value
+ * if the simulator is running in verbose mode, then exit with ENOEXEC.
+ *
+ */
+static void exit_error(unsigned int rc, unsigned int line)
+{
+ if (opt_verbose)
+ fprintf(stderr, "ERROR: errno = %d, line = %d\n", rc, line);
+ else
+ fprintf(stderr, "ERROR\n");
+ exit(ENOEXEC);
+}
+
+/**
+ * Handle a simulator return/action
+ * @param action the return value
+ * @param line the line number
+ *
+ * Display the action to stdout and exit with 0.
+ *
+ */
+static void end_action(uint32_t action, unsigned int line)
+{
+ uint32_t act = action & SECCOMP_RET_ACTION;
+ uint32_t data = action & SECCOMP_RET_DATA;
+
+ switch (act) {
+ case SECCOMP_RET_KILL:
+ fprintf(stdout, "KILL\n");
+ break;
+ case SECCOMP_RET_TRAP:
+ fprintf(stdout, "TRAP\n");
+ break;
+ case SECCOMP_RET_ERRNO:
+ fprintf(stdout, "ERRNO(%u)\n", data);
+ break;
+ case SECCOMP_RET_TRACE:
+ fprintf(stdout, "TRACE(%u)\n", data);
+ break;
+ case SECCOMP_RET_ALLOW:
+ fprintf(stdout, "ALLOW\n");
+ break;
+ default:
+ exit_error(EDOM, line);
+ }
+
+ exit(0);
+}
+
+/**
+ * Execute a BPF program
+ * @param prg the loaded BPF program
+ * @param sys_data the syscall record being tested
+ *
+ * Simulate the BPF program with the given syscall record.
+ *
+ */
+static void bpf_execute(const struct bpf_program *prg,
+ const struct seccomp_data *sys_data)
+{
+ unsigned int ip, ip_c;
+ struct sim_state state;
+ bpf_instr_raw *bpf;
+ unsigned char *sys_data_b = (unsigned char *)sys_data;
+
+ /* initialize the machine state */
+ ip_c = 0;
+ ip = 0;
+ memset(&state, 0, sizeof(state));
+
+ while (ip < prg->i_cnt) {
+ /* get the instruction and bump the ip */
+ ip_c = ip;
+ bpf = &prg->i[ip++];
+
+ switch (bpf->code) {
+ case BPF_LD+BPF_W+BPF_ABS:
+ if (bpf->k < BPF_SYSCALL_MAX)
+ state.acc = *((uint32_t *)&sys_data_b[bpf->k]);
+ else
+ exit_error(ERANGE, ip_c);
+ break;
+ case BPF_ALU+BPF_OR+BPF_K:
+ state.acc |= bpf->k;
+ break;
+ case BPF_ALU+BPF_AND+BPF_K:
+ state.acc &= bpf->k;
+ break;
+ case BPF_JMP+BPF_JA:
+ ip += bpf->k;
+ break;
+ case BPF_JMP+BPF_JEQ+BPF_K:
+ if (state.acc == bpf->k)
+ ip += bpf->jt;
+ else
+ ip += bpf->jf;
+ break;
+ case BPF_JMP+BPF_JGT+BPF_K:
+ if (state.acc > bpf->k)
+ ip += bpf->jt;
+ else
+ ip += bpf->jf;
+ break;
+ case BPF_JMP+BPF_JGE+BPF_K:
+ if (state.acc >= bpf->k)
+ ip += bpf->jt;
+ else
+ ip += bpf->jf;
+ break;
+ case BPF_RET+BPF_K:
+ end_action(bpf->k, ip_c);
+ break;
+ default:
+ /* since we don't support the full bpf language just
+ * yet, this could be either a fault or an error, we'll
+ * treat it as a fault until we provide full support */
+ exit_fault(EOPNOTSUPP);
+ }
+ }
+
+ /* if we've reached here there is a problem with the program */
+ exit_error(ERANGE, ip_c);
+}
+
+/**
+ * main
+ */
+int main(int argc, char *argv[])
+{
+ int opt;
+ char *opt_file = NULL;
+ FILE *file;
+ size_t file_read_len;
+ struct seccomp_data sys_data;
+ struct bpf_program bpf_prg;
+
+ /* clear the syscall record */
+ memset(&sys_data, 0, sizeof(sys_data));
+
+ /* parse the command line */
+ while ((opt = getopt(argc, argv, "a:f:h:s:v0:1:2:3:4:5:")) > 0) {
+ switch (opt) {
+ case 'a':
+ if (strcmp(optarg, "x86") == 0)
+ sys_data.arch = AUDIT_ARCH_I386;
+ else if (strcmp(optarg, "x86_64") == 0)
+ sys_data.arch = AUDIT_ARCH_X86_64;
+ else if (strcmp(optarg, "x32") == 0)
+ sys_data.arch = AUDIT_ARCH_X86_64;
+ else if (strcmp(optarg, "arm") == 0)
+ sys_data.arch = AUDIT_ARCH_ARM;
+ else
+ exit_fault(EINVAL);
+ break;
+ case 'f':
+ opt_file = strdup(optarg);
+ if (opt_file == NULL)
+ exit_fault(ENOMEM);
+ break;
+ case 's':
+ sys_data.nr = strtol(optarg, NULL, 0);
+ break;
+ case 'v':
+ opt_verbose = 1;
+ break;
+ case '0':
+ sys_data.args[0] = strtoull(optarg, NULL, 0);
+ break;
+ case '1':
+ sys_data.args[1] = strtoull(optarg, NULL, 0);
+ break;
+ case '2':
+ sys_data.args[2] = strtoull(optarg, NULL, 0);
+ break;
+ case '3':
+ sys_data.args[3] = strtoull(optarg, NULL, 0);
+ break;
+ case '4':
+ sys_data.args[4] = strtoull(optarg, NULL, 0);
+ break;
+ case '5':
+ sys_data.args[5] = strtoull(optarg, NULL, 0);
+ break;
+ case 'h':
+ default:
+ /* usage information */
+ exit_usage(argv[0]);
+ }
+ }
+
+ /* allocate space for the bpf program */
+ /* XXX - we should make this dynamic */
+ bpf_prg.i_cnt = 0;
+ bpf_prg.i = calloc(BPF_PRG_MAX_LEN, sizeof(*bpf_prg.i));
+ if (bpf_prg.i == NULL)
+ exit_fault(ENOMEM);
+
+ /* load the bpf program */
+ file = fopen(opt_file, "r");
+ if (file == NULL)
+ exit_fault(errno);
+ do {
+ file_read_len = fread(&(bpf_prg.i[bpf_prg.i_cnt]),
+ sizeof(*bpf_prg.i), 1, file);
+ if (file_read_len == 1)
+ bpf_prg.i_cnt++;
+
+ /* check the size */
+ if (bpf_prg.i_cnt == BPF_PRG_MAX_LEN)
+ exit_fault(E2BIG);
+ } while (file_read_len > 0);
+ fclose(file);
+
+ /* execute the bpf program */
+ bpf_execute(&bpf_prg, &sys_data);
+
+ /* we should never reach here */
+ exit_fault(EFAULT);
+ return 0;
+}
--- /dev/null
+/**
+ * Syscall resolver
+ *
+ * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
+ * Author: Paul Moore <pmoore@redhat.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>.
+ */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../src/arch.h"
+#include "../src/arch-x86.h"
+#include "../src/arch-x86_64.h"
+#include "../src/arch-x32.h"
+#include "../src/arch-arm.h"
+
+/**
+ * Print the usage information to stderr and exit
+ * @param program the name of the current program being invoked
+ *
+ * Print the usage information and exit with EINVAL.
+ *
+ */
+static void exit_usage(const char *program)
+{
+ fprintf(stderr,
+ "usage: %s [-h] [-a <arch>] [-t] <name>|<number>\n",
+ program);
+ exit(EINVAL);
+}
+
+/**
+ * main
+ */
+int main(int argc, char *argv[])
+{
+ int opt;
+ int translate = 0;
+ const struct arch_def *arch = arch_def_native;
+ int sys_num;
+ const char *sys_name;
+
+ /* parse the command line */
+ while ((opt = getopt(argc, argv, "a:ht")) > 0) {
+ switch (opt) {
+ case 'a':
+ if (strcmp(optarg, "x86") == 0)
+ arch = &arch_def_x86;
+ else if (strcmp(optarg, "x86_64") == 0)
+ arch = &arch_def_x86_64;
+ else if (strcmp(optarg, "x32") == 0)
+ arch = &arch_def_x32;
+ else if (strcmp(optarg, "arm") == 0)
+ arch = &arch_def_arm;
+ else
+ exit_usage(argv[0]);
+ break;
+ case 't':
+ translate = 1;
+ break;
+ case 'h':
+ default:
+ /* usage information */
+ exit_usage(argv[0]);
+ }
+ }
+
+ /* sanity checks */
+ if (optind >= argc)
+ exit_usage(argv[0]);
+
+ /* perform the syscall lookup */
+ if (isdigit(argv[optind][0]) || argv[optind][0] == '-') {
+ sys_num = atoi(argv[optind]);
+ sys_name = arch_syscall_resolve_num(arch, sys_num);
+ printf("%s\n", sys_name);
+ } else {
+ sys_num = arch_syscall_resolve_name(arch, argv[optind]);
+ if (translate != 0)
+ /* ignore errors and just output the resolved number */
+ arch_syscall_rewrite(arch, 0, &sys_num);
+ printf("%d\n", sys_num);
+ }
+
+ return 0;
+}
--- /dev/null
+/* automatically generated - do not edit */
+#ifndef _VERSION_H
+#define _VERSION_H
+#define VERSION_RELEASE "2.1.1"
+#define VERSION_MAJOR 2
+#define VERSION_MINOR 1
+#define VERSION_MICRO 1
+#endif
--- /dev/null
+#
+# version_info - version information for seccomp library
+#
+
+# version components
+VERSION_MAJOR=2
+VERSION_MINOR=1
+VERSION_MICRO=1