libseccomp-2.1.1/0000755000175000001440000000000012234472367013065 5ustar pmooreuserslibseccomp-2.1.1/configure0000755000175000001440000001307112234471363014771 0ustar pmooreusers#!/bin/bash # # Enhanced Seccomp Library Configure Script # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # # 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: * 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 libseccomp-2.1.1/libseccomp.pc.in0000644000175000001440000000175011763665475016153 0ustar pmooreusers# # Enhanced Seccomp Library pkg-config Configuration # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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 libseccomp-2.1.1/LICENSE0000644000175000001440000005755411740660643014107 0ustar pmooreusers 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. libseccomp-2.1.1/include/0000755000175000001440000000000012234471720014500 5ustar pmooreuserslibseccomp-2.1.1/include/seccomp.h.in0000644000175000001440000007450112234256466016726 0ustar pmooreusers/** * Seccomp Library * * Copyright (c) 2012,2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _SECCOMP_H #define _SECCOMP_H #include #include #include #include #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 libseccomp-2.1.1/include/Makefile0000644000175000001440000000236612102053330016132 0ustar pmooreusers# # Enhanced Seccomp Library Makefile # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # # # 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) libseccomp-2.1.1/doc/0000755000175000001440000000000012151446370013623 5ustar pmooreuserslibseccomp-2.1.1/doc/Makefile0000644000175000001440000000335412151446370015270 0ustar pmooreusers# # Enhanced Seccomp Library Makefile # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # # # 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) libseccomp-2.1.1/doc/man/0000755000175000001440000000000012151446370014376 5ustar pmooreuserslibseccomp-2.1.1/doc/man/man1/0000755000175000001440000000000012151446370015232 5ustar pmooreuserslibseccomp-2.1.1/doc/man/man1/scmp_sys_resolver.10000644000175000001440000000516612151446370021105 0ustar pmooreusers.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 libseccomp-2.1.1/doc/man/man3/0000755000175000001440000000000012124420575015233 5ustar pmooreuserslibseccomp-2.1.1/doc/man/man3/seccomp_load.30000644000175000001440000000526612100325364017752 0ustar pmooreusers.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 .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 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 .\" ////////////////////////////////////////////////////////////////////////// .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) libseccomp-2.1.1/doc/man/man3/seccomp_init.30000644000175000001440000001056712061411036017774 0ustar pmooreusers.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 .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 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 .\" ////////////////////////////////////////////////////////////////////////// .SH SEE ALSO .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_release (3) libseccomp-2.1.1/doc/man/man3/seccomp_attr_get.30000644000175000001440000000003411743036611020636 0ustar pmooreusers.so man3/seccomp_attr_set.3 libseccomp-2.1.1/doc/man/man3/seccomp_arch_exist.30000644000175000001440000000003412053011666021154 0ustar pmooreusers.so man3/seccomp_arch_add.3 libseccomp-2.1.1/doc/man/man3/seccomp_syscall_resolve_num_arch.30000644000175000001440000000005012075354106024111 0ustar pmooreusers.so man3/seccomp_syscall_resolve_name.3 libseccomp-2.1.1/doc/man/man3/seccomp_arch_remove.30000644000175000001440000000003412053011666021315 0ustar pmooreusers.so man3/seccomp_arch_add.3 libseccomp-2.1.1/doc/man/man3/seccomp_arch_native.30000644000175000001440000000003412054774430021314 0ustar pmooreusers.so man3/seccomp_arch_add.3 libseccomp-2.1.1/doc/man/man3/seccomp_merge.30000644000175000001440000000735612100325364020134 0ustar pmooreusers.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 .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 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 .\" ////////////////////////////////////////////////////////////////////////// .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) libseccomp-2.1.1/doc/man/man3/seccomp_export_bpf.30000644000175000001440000000701712061411036021175 0ustar pmooreusers.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 .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 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 .\" ////////////////////////////////////////////////////////////////////////// .SH SEE ALSO .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_init (3), .BR seccomp_release (3) libseccomp-2.1.1/doc/man/man3/seccomp_syscall_resolve_name.30000644000175000001440000000757712100325364023253 0ustar pmooreusers.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 .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 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 .\" ////////////////////////////////////////////////////////////////////////// .SH SEE ALSO .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_rule_add (3), .BR seccomp_rule_add_exact (3) libseccomp-2.1.1/doc/man/man3/seccomp_rule_add_array.30000644000175000001440000000003412124420575022002 0ustar pmooreusers.so man3/seccomp_rule_add.3 libseccomp-2.1.1/doc/man/man3/seccomp_rule_add_exact_array.30000644000175000001440000000003412124420575023166 0ustar pmooreusers.so man3/seccomp_rule_add.3 libseccomp-2.1.1/doc/man/man3/seccomp_rule_add_exact.30000644000175000001440000000003411737351557022004 0ustar pmooreusers.so man3/seccomp_rule_add.3 libseccomp-2.1.1/doc/man/man3/seccomp_attr_set.30000644000175000001440000000776112061411036020660 0ustar pmooreusers.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 .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 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 .\" ////////////////////////////////////////////////////////////////////////// .SH SEE ALSO .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_init (3), .BR seccomp_reset (3), .BR seccomp_load (3) libseccomp-2.1.1/doc/man/man3/seccomp_release.30000644000175000001440000000512112061411036020437 0ustar pmooreusers.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 .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 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 .\" ////////////////////////////////////////////////////////////////////////// .SH SEE ALSO .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_init (3), .BR seccomp_reset (3) libseccomp-2.1.1/doc/man/man3/seccomp_reset.30000644000175000001440000000003011737351557020157 0ustar pmooreusers.so man3/seccomp_init.3 libseccomp-2.1.1/doc/man/man3/seccomp_export_pfc.30000644000175000001440000000003611746233754021212 0ustar pmooreusers.so man3/seccomp_export_bpf.3 libseccomp-2.1.1/doc/man/man3/seccomp_syscall_resolve_name_arch.30000644000175000001440000000005012075354106024232 0ustar pmooreusers.so man3/seccomp_syscall_resolve_name.3 libseccomp-2.1.1/doc/man/man3/seccomp_arch_add.30000644000175000001440000001073212100325364020552 0ustar pmooreusers.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 .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 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 .\" ////////////////////////////////////////////////////////////////////////// .SH SEE ALSO .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_init (3), .BR seccomp_reset (3), .BR seccom_merge (3) libseccomp-2.1.1/doc/man/man3/seccomp_rule_add.30000644000175000001440000002064612124420575020617 0ustar pmooreusers.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 .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 #include #include #include #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 .\" ////////////////////////////////////////////////////////////////////////// .SH SEE ALSO .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_syscall_priority (3), .BR seccomp_load (3) libseccomp-2.1.1/doc/man/man3/seccomp_syscall_priority.30000644000175000001440000000737312100325364022447 0ustar pmooreusers.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 .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 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 .\" ////////////////////////////////////////////////////////////////////////// .SH SEE ALSO .\" ////////////////////////////////////////////////////////////////////////// .BR seccomp_rule_add (3), .BR seccomp_rule_add_exact (3) libseccomp-2.1.1/version_info0000644000175000001440000000020312234471363015476 0ustar pmooreusers# # version_info - version information for seccomp library # # version components VERSION_MAJOR=2 VERSION_MINOR=1 VERSION_MICRO=1 libseccomp-2.1.1/tags0000644000175000001440000014654012173757431013760 0ustar pmooreusers!_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 '$/;" 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: libseccomp-2.1.1/tools/0000755000175000001440000000000012234472367014225 5ustar pmooreuserslibseccomp-2.1.1/tools/check-syntax0000755000175000001440000000462712234256466016565 0ustar pmooreusers#!/bin/bash # # libseccomp code syntax checking tool # # Copyright (c) 2013 Red Hat # Author: Paul Moore # # # 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 . # 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 libseccomp-2.1.1/tools/scmp_app_inspector0000755000175000001440000000453712151446320020040 0ustar pmooreusers#!/bin/bash # # Runtime syscall inspector # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # #### # 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 ] []" 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 libseccomp-2.1.1/tools/scmp_arch_detect.c0000644000175000001440000000343212234256466017662 0ustar pmooreusers/** * Architecture Detector * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include /** * 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; } libseccomp-2.1.1/tools/scmp_sys_resolver.c0000644000175000001440000000476212234256466020163 0ustar pmooreusers/** * Syscall resolver * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include #include #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 ] [-t] |\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; } libseccomp-2.1.1/tools/scmp_bpf_disasm.c0000644000175000001440000001555112234256466017531 0ustar pmooreusers/** * BPF Disassembler * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include #include #include #include #include #include #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 []\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; } libseccomp-2.1.1/tools/scmp_bpf_sim.c0000644000175000001440000001554112234256466017040 0ustar pmooreusers/** * BPF Simulator * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include #include #include #include #include #include #include #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 [-v]" " -a -s [-0 ] ... [-5 ]\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; } libseccomp-2.1.1/tools/bpf.h0000644000175000001440000000605011741315243015135 0ustar pmooreusers/** * BPF Language Definitions * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _BPF_H #define _BPF_H #include #include /* 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 libseccomp-2.1.1/tools/Makefile0000644000175000001440000000231412151446352015656 0ustar pmooreusers# # Enhanced Seccomp Library Makefile # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # # # 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) libseccomp-2.1.1/version.h0000644000175000001440000000030112234471426014710 0ustar pmooreusers/* 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 libseccomp-2.1.1/tests/0000755000175000001440000000000012234472367014227 5ustar pmooreuserslibseccomp-2.1.1/tests/08-sim-subtree_checks.c0000644000175000001440000001137112227554505020377 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/07-sim-db_bug_looping.py0000755000175000001440000000247212234256466020574 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/regression0000755000175000001440000005661512234256466016352 0ustar pmooreusers#!/bin/bash # # libseccomp regression test automation script # # Copyright IBM Corp. 2012 # Author: Corey Bryant # # # 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 . # 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 ] [-s SINGLE_TEST] [-t ] [-T ] 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 $($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 libseccomp-2.1.1/tests/23-sim-arch_all_basic.c0000644000175000001440000000432112125061272020275 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/01-sim-allow.c0000644000175000001440000000220412230310300016461 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/10-sim-syscall_priority_post.py0000755000175000001440000000253112104742126022256 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/01-sim-allow.tests0000644000175000001440000000055712234256466017444 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # 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 libseccomp-2.1.1/tests/23-sim-arch_all_basic.py0000755000175000001440000000303412125061272020506 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/08-sim-subtree_checks.py0000755000175000001440000000747212104742126020607 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/07-sim-db_bug_looping.tests0000644000175000001440000000100512234256466021272 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # 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 libseccomp-2.1.1/tests/21-live-basic_allow.c0000644000175000001440000000337112104742310020013 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/05-sim-long_jumps.tests0000644000175000001440000000237112234256466020503 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # 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 libseccomp-2.1.1/tests/02-sim-basic.py0000755000175000001440000000227112104742126016661 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/23-sim-arch_all_basic.tests0000644000175000001440000000142312234256466021231 0ustar pmooreusers# # libseccomp regression test automation data # # # Copyright (c) 2013 Red Hat # Author: Paul Moore # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/04-sim-multilevel_chains.c0000644000175000001440000000427312230002017021070 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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); } libseccomp-2.1.1/tests/11-basic-basic_errors.tests0000644000175000001440000000027112104742126021253 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # test type: basic # Test command 11-basic-basic_errors libseccomp-2.1.1/tests/07-sim-db_bug_looping.c0000644000175000001440000000321012104742126020337 0ustar pmooreusers/** * Seccomp Library test program * * Copyright IBM Corp. 2012 * Author: Ashley Lai */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/09-sim-syscall_priority_pre.tests0000644000175000001440000000130012234256466022602 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # 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 libseccomp-2.1.1/tests/16-sim-arch_basic.c0000644000175000001440000000463312125061470017455 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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); } libseccomp-2.1.1/tests/testdiff0000755000175000001440000000457712234256466016002 0ustar pmooreusers#!/bin/bash # # libseccomp test diff generator # # Copyright (c) 2013 Red Hat # Author: Paul Moore # # # 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 . # #### # 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 libseccomp-2.1.1/tests/09-sim-syscall_priority_pre.c0000644000175000001440000000342512104742126021661 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/05-sim-long_jumps.c0000644000175000001440000000355712104742126017557 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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); } libseccomp-2.1.1/tests/03-sim-basic_chains.py0000755000175000001440000000250312104742126020205 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/14-sim-reset.c0000644000175000001440000000261312104742126016514 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/04-sim-multilevel_chains.tests0000644000175000001440000000354312234256466022036 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # 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 libseccomp-2.1.1/tests/20-live-basic_die.py0000755000175000001440000000237112104742310017645 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2013 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/19-sim-missing_syscalls.c0000644000175000001440000000304612104742126020766 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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); } libseccomp-2.1.1/tests/14-sim-reset.tests0000644000175000001440000000136312234256466017450 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2012 Red Hat # Author: Paul Moore # 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 libseccomp-2.1.1/tests/01-sim-allow.py0000755000175000001440000000202412104742126016711 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/25-sim-multilevel_chains_adv.py0000755000175000001440000000243412134304540022144 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2013 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/03-sim-basic_chains.c0000644000175000001440000000340112230017060017762 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/18-sim-basic_whitelist.tests0000644000175000001440000000204712234256466021507 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2013 Red Hat # Author: Paul Moore # 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 libseccomp-2.1.1/tests/util.py0000644000175000001440000000574612104742166015563 0ustar pmooreusers# # Seccomp Library utility code for tests # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # """ 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; libseccomp-2.1.1/tests/11-basic-basic_errors.c0000644000175000001440000000777712234256466020370 0ustar pmooreusers/** * Seccomp Library test program * * Copyright IBM Corp. 2012 * Author: Corey Bryant */ /* * 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 . */ #include #include #include 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; } libseccomp-2.1.1/tests/16-sim-arch_basic.tests0000644000175000001440000000176612234256466020415 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2012 Red Hat # Author: Paul Moore # 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 libseccomp-2.1.1/tests/17-sim-arch_merge.tests0000644000175000001440000000153212234256466020423 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2012 Red Hat # Author: Paul Moore # 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 libseccomp-2.1.1/tests/testgen0000755000175000001440000001040412234256466015625 0ustar pmooreusers#!/bin/bash # # libseccomp test output generator # # Copyright (c) 2013 Red Hat # Author: Paul Moore # # # 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 . # #### # 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 libseccomp-2.1.1/tests/22-sim-basic_chains_array.c0000644000175000001440000000357412124420575021207 0ustar pmooreusers/** * Seccomp Library test program * * Author: Paul Moore , Vitaly Shukela */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/18-sim-basic_whitelist.c0000644000175000001440000000337512104742126020561 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/21-live-basic_allow.tests0000644000175000001440000000031312104742310020724 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2013 Red Hat # Author: Paul Moore # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/13-basic-attrs.tests0000644000175000001440000000026212104742126017735 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # test type: basic # Test command 13-basic-attrs libseccomp-2.1.1/tests/13-basic-attrs.py0000755000175000001440000000264012104742126017230 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/15-basic-resolver.tests0000644000175000001440000000030112104742126020435 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2012 Red Hat # Author: Paul Moore # test type: basic # Test command 15-basic-resolver libseccomp-2.1.1/tests/11-basic-basic_errors.py0000755000175000001440000000413112104742126020543 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/25-sim-multilevel_chains_adv.c0000644000175000001440000000272712213414025021736 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/18-sim-basic_whitelist.py0000755000175000001440000000247712104742126020774 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2013 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/util.c0000644000175000001440000001122212234256466015346 0ustar pmooreusers/** * Seccomp Library utility code for tests * * Copyright (c) 2012 Red Hat * Author: Eric Paris */ /* * 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 . */ #include #include #include #include #include #include #include #include #include #include #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; } libseccomp-2.1.1/tests/16-sim-arch_basic.py0000755000175000001440000000313112234256466017672 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/13-basic-attrs.c0000644000175000001440000000333712234256466017036 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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); } libseccomp-2.1.1/tests/15-basic-resolver.py0000755000175000001440000000305412104742126017736 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/10-sim-syscall_priority_post.c0000644000175000001440000000342512104742126022050 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/00-test.c0000644000175000001440000000243112137501367015562 0ustar pmooreusers /* * 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 . */ #include #include #include #include #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; }libseccomp-2.1.1/tests/08-sim-subtree_checks.tests0000644000175000001440000000325512234256466021324 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # 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 libseccomp-2.1.1/tests/17-sim-arch_merge.py0000755000175000001440000000315612234256466017720 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/24-live-arg_allow.tests0000644000175000001440000000031112125061272020421 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2013 Red Hat # Author: Paul Moore # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/24-live-arg_allow.c0000644000175000001440000000402312234256466017521 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include #include #include #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); } libseccomp-2.1.1/tests/02-sim-basic.tests0000644000175000001440000000143412234256466017403 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # 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 libseccomp-2.1.1/tests/19-sim-missing_syscalls.py0000755000175000001440000000236612104742126021203 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2013 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/12-sim-basic_masked_ops.py0000755000175000001440000000362012104742126021066 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/25-sim-multilevel_chains_adv.tests0000644000175000001440000000215012234256466022664 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2013 Red Hat # Author: Paul Moore * Author: Paul Moore */ /* * 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 . */ /* * Just like mode 1 seccomp we allow 4 syscalls: * read, write, exit, and rt_sigreturn */ #include #include #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); } libseccomp-2.1.1/tests/17-sim-arch_merge.c0000644000175000001440000000527712104742126017502 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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; } libseccomp-2.1.1/tests/12-sim-basic_masked_ops.c0000644000175000001440000000427212104742126020661 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/tests/21-live-basic_allow.py0000755000175000001440000000323712104742310020225 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2013 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/06-sim-actions.tests0000644000175000001440000000124112234256466017762 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # 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 libseccomp-2.1.1/tests/Makefile0000644000175000001440000000367612234256466015703 0ustar pmooreusers# # Enhanced Seccomp Library Makefile # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # # # 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 libseccomp-2.1.1/tests/06-sim-actions.c0000644000175000001440000000307012104742126017031 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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); } libseccomp-2.1.1/tests/05-sim-long_jumps.py0000755000175000001440000000275412104742126017766 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/22-sim-basic_chains_array.tests0000644000175000001440000000204112234256466022123 0ustar pmooreusers# # libseccomp regression test automation data # # Author: Vitaly Shukela # 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 libseccomp-2.1.1/tests/19-sim-missing_syscalls.tests0000644000175000001440000000064012234256466021716 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2013 Red Hat # Author: Paul Moore # 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 libseccomp-2.1.1/tests/10-sim-syscall_priority_post.tests0000644000175000001440000000131012234256466022772 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright IBM Corp. 2012 # Author: Corey Bryant # 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 libseccomp-2.1.1/tests/22-sim-basic_chains_array.py0000755000175000001440000000272512124420575021415 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2013 Red Hat # Author: Paul Moore # # # 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 . # # 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; libseccomp-2.1.1/tests/util.h0000644000175000001440000000213212104742166015344 0ustar pmooreusers/** * Seccomp Library utility code for tests * * Copyright IBM Corp. 2012 * Author: Corey Bryant */ /* * 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 . */ #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 libseccomp-2.1.1/tests/04-sim-multilevel_chains.py0000755000175000001440000000334212104742126021311 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/14-sim-reset.py0000755000175000001440000000213612104742126016725 0ustar pmooreusers#!/usr/bin/env python # # Seccomp Library test program # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/tests/15-basic-resolver.c0000644000175000001440000000335512104742126017531 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include 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; } libseccomp-2.1.1/tests/20-live-basic_die.tests0000644000175000001440000000036712104742310020357 0ustar pmooreusers# # libseccomp regression test automation data # # Copyright (c) 2013 Red Hat # Author: Paul Moore # 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 libseccomp-2.1.1/tests/20-live-basic_die.c0000644000175000001440000000276612104742310017444 0ustar pmooreusers/** * Seccomp Library test program * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/macros.mk0000644000175000001440000001240012234256466014677 0ustar pmooreusers# # Enhanced Seccomp Library Build Macros # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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) libseccomp-2.1.1/src/0000755000175000001440000000000012234472200013636 5ustar pmooreuserslibseccomp-2.1.1/src/db.h0000644000175000001440000001226212234256466014415 0ustar pmooreusers/** * Enhanced Seccomp Filter DB * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _FILTER_DB_H #define _FILTER_DB_H #include #include #include #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 libseccomp-2.1.1/src/arch-x86.h0000644000175000001440000000233712134321276015361 0ustar pmooreusers/** * Enhanced Seccomp x86 Specific Code * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _ARCH_X86_H #define _ARCH_X86_H #include #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 libseccomp-2.1.1/src/db.c0000644000175000001440000010174712234256466014417 0ustar pmooreusers/** * Enhanced Seccomp Filter DB * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include #include #include #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; } libseccomp-2.1.1/src/arch-arm.c0000644000175000001440000000176412230313110015472 0ustar pmooreusers/** * Enhanced Seccomp ARM Specific Code * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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, }; libseccomp-2.1.1/src/python/0000755000175000001440000000000012234472222015163 5ustar pmooreuserslibseccomp-2.1.1/src/python/setup.py0000644000175000001440000000257112053011666016702 0ustar pmooreusers#!/usr/bin/env python # # Enhanced Seccomp Library Python Module Build Script # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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"]) ] ) libseccomp-2.1.1/src/python/libseccomp.pxd0000644000175000001440000000615112125061224020016 0ustar pmooreusers# # Seccomp Library Python Bindings # # Copyright (c) 2012,2013 Red Hat # Author: Paul Moore # # # 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 . # 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; libseccomp-2.1.1/src/python/seccomp.pyx0000644000175000001440000005310112234256466017370 0ustar pmooreusers# # Seccomp Library Python Bindings # # Copyright (c) 2012,2013 Red Hat # Author: Paul Moore # # # 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 . # """ 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 ' __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, &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; libseccomp-2.1.1/src/python/Makefile0000644000175000001440000000225112053011666016623 0ustar pmooreusers# # Enhanced Seccomp Library Python Bindings Makefile # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # # # 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 libseccomp-2.1.1/src/gen_bpf.c0000644000175000001440000013211412234256466015422 0ustar pmooreusers/** * Seccomp BPF Translator * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include #include #include #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); } libseccomp-2.1.1/src/arch-x86.c0000644000175000001440000000672412230313110015341 0ustar pmooreusers/** * Enhanced Seccomp x86 Specific Code * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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; } libseccomp-2.1.1/src/gen_pfc.c0000644000175000001440000002032412234256466015422 0ustar pmooreusers/** * Seccomp Pseudo Filter Code (PFC) Generator * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include #include /* NOTE: needed for the arch->token decoding in _pfc_arch() */ #include #include #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; } libseccomp-2.1.1/src/gen_bpf.h0000644000175000001440000000227012230221206015402 0ustar pmooreusers/** * Seccomp BPF Translator * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _TRANSLATOR_BPF_H #define _TRANSLATOR_BPF_H #include #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 libseccomp-2.1.1/src/api.c0000644000175000001440000003524712234256466014604 0ustar pmooreusers/** * Seccomp Library API * * Copyright (c) 2012,2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include #include #include #include #include #include #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; } libseccomp-2.1.1/src/arch-x86_64-syscalls.c0000644000175000001440000002704512234256466017534 0ustar pmooreusers/** * Enhanced Seccomp x86_64 Syscall Table * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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; } libseccomp-2.1.1/src/arch-arm-syscalls.c0000644000175000001440000004572312234256466017360 0ustar pmooreusers/** * Enhanced Seccomp ARM Syscall Table * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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; } libseccomp-2.1.1/src/arch-x32.c0000644000175000001440000000207612230313110015324 0ustar pmooreusers/** * Enhanced Seccomp x32 Specific Code * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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, }; libseccomp-2.1.1/src/arch-x86-syscalls.c0000644000175000001440000002625212234256466017222 0ustar pmooreusers/** * Enhanced Seccomp x86 Syscall Table * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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; } libseccomp-2.1.1/src/arch-x32.h0000644000175000001440000000206012125061272015336 0ustar pmooreusers/** * Enhanced Seccomp x32 Specific Code * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _ARCH_X32_H #define _ARCH_X32_H #include #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 libseccomp-2.1.1/src/arch-x86_64.h0000644000175000001440000000222012125061224015653 0ustar pmooreusers/** * Enhanced Seccomp x86_64 Specific Code * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _ARCH_x86_64_H #define _ARCH_x86_64_H #include #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 libseccomp-2.1.1/src/arch-arm.h0000644000175000001440000000201212125061224015473 0ustar pmooreusers/** * Enhanced Seccomp ARM Specific Code * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _ARCH_ARM_H #define _ARCH_ARM_H #include #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 libseccomp-2.1.1/src/arch.c0000644000175000001440000002061212230313467014725 0ustar pmooreusers/** * Enhanced Seccomp Architecture/Machine Specific Code * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #include #include #include #include #include #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; } libseccomp-2.1.1/src/hash.c0000644000175000001440000004047612234256466014756 0ustar pmooreusers/** * Seccomp Library hash code * * Release under the Public Domain * Author: Bob Jenkins */ /* * 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 #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; iendian == 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); } libseccomp-2.1.1/src/gen_pfc.h0000644000175000001440000000156712050260340015415 0ustar pmooreusers/** * Seccomp String Translator * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _TRANSLATOR_STR_H #define _TRANSLATOR_STR_H #include "db.h" int gen_pfc_generate(const struct db_filter_col *col, int fd); #endif libseccomp-2.1.1/src/hash.h0000644000175000001440000000126111716316743014747 0ustar pmooreusers/** * The "lookup3.c" Hash Implementation from Bob Jenkins * * Original Author: Bob Jenkins * 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 uint32_t jhash(const void *key, size_t length, uint32_t initval); #endif libseccomp-2.1.1/src/arch-x32-syscalls.c0000644000175000001440000000337312230313110017160 0ustar pmooreusers/** * Enhanced Seccomp x32 Syscall Table * * Copyright (c) 2013 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #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); } libseccomp-2.1.1/src/arch.h0000644000175000001440000000617512134321012014726 0ustar pmooreusers/** * Enhanced Seccomp Architecture/Machine Specific Code * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _ARCH_H #define _ARCH_H #include #include #include #include #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 | grep '__NR_' * where 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 | 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 libseccomp-2.1.1/src/system.h0000644000175000001440000000543412231560107015342 0ustar pmooreusers/** * Seccomp System Information * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #ifndef _SYSTEM_H #define _SYSTEM_H #include #include #include #ifdef CONF_SYSINC_SECCOMP /* system header file */ #include #else /* NOTE: the definitions below were taken from the Linux Kernel sources */ #include /* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, ) */ #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 . * @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 libseccomp-2.1.1/src/Makefile0000644000175000001440000000346112234256466015320 0ustar pmooreusers# # Enhanced Seccomp Library Makefile # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # # # 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 libseccomp-2.1.1/src/arch-x86_64.c0000644000175000001440000000200312230313110015634 0ustar pmooreusers/** * Enhanced Seccomp x86_64 Specific Code * * Copyright (c) 2012 Red Hat * Author: Paul Moore */ /* * 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 . */ #include #include #include #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, }; libseccomp-2.1.1/CHANGELOG0000644000175000001440000000377612234470066014306 0ustar pmooreuserslibseccomp: 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 libseccomp-2.1.1/install.mk0000644000175000001440000000213312004002464015041 0ustar pmooreusers# # Enhanced Seccomp Library Installation Defaults # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # 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) libseccomp-2.1.1/Makefile0000644000175000001440000000644712234256466014540 0ustar pmooreusers# # Enhanced Seccomp Library Makefile # # Copyright (c) 2012 Red Hat # Author: Paul Moore # # # 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 . # # # 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) libseccomp-2.1.1/README0000644000175000001440000000316412004001242013720 0ustar pmooreuserslibseccomp: 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. libseccomp-2.1.1/CREDITS0000644000175000001440000000101212234470066014071 0ustar pmooreuserslibseccomp: Contributors =============================================================================== http://libseccomp.sf.net Andy Lutomirski Ashley Lai Corey Bryant Eduardo Otubo Eric Paris Jake Edge Joe MacDonald Kees Cook Paul Moore Thiago Marcos P. Santos Vitaly Vi Shukela